Initial enums working

This commit is contained in:
Krzosa Karol
2022-05-31 11:50:36 +02:00
parent 5e0aabb1cb
commit 627e2bad88
8 changed files with 168 additions and 17 deletions

View File

@@ -28,6 +28,7 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){
case TYPE_POINTER:{gen_simple_decl_prefix(ast->base); gen("*");} break; case TYPE_POINTER:{gen_simple_decl_prefix(ast->base); gen("*");} break;
case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break; case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break;
case TYPE_LAMBDA:break; case TYPE_LAMBDA:break;
case TYPE_ENUM:
case TYPE_STRUCT: { case TYPE_STRUCT: {
auto constant = (Ast_Const *)ast->ast->parent; auto constant = (Ast_Const *)ast->ast->parent;
auto name = constant->name; auto name = constant->name;
@@ -48,7 +49,7 @@ gen_simple_decl_postfix(Ast_Resolved_Type *ast){
case TYPE_POINTER: gen_simple_decl_postfix(ast->base); break; case TYPE_POINTER: gen_simple_decl_postfix(ast->base); break;
case TYPE_ARRAY: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break; case TYPE_ARRAY: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
case TYPE_LAMBDA:break; case TYPE_LAMBDA:break;
case TYPE_STRUCT:break; case TYPE_ENUM: case TYPE_STRUCT:break;
invalid_default_case; invalid_default_case;
} }
} }
@@ -323,7 +324,28 @@ gen_ast(Ast *ast){
genln("};"); genln("};");
} }
else{ else{
// type alias // Type alias
}
}
else if(sym->type_val->kind == TYPE_ENUM){
Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast;
assert(enu->kind == AST_ENUM);
if(node->value->kind == AST_ENUM){
gen("enum %s{", node->name.str);
// @todo add typespec
global_indent++;
For(enu->members){
genln("%s", it->name.str);
gen(" = ");
Sym *value_sym = resolved_get(it);
gen("%d", value_sym->int_val);
gen(",");
}
global_indent--;
genln("};");
}
else{
// Type alias
} }
} }
else{ else{

5
enums.kl Normal file
View File

@@ -0,0 +1,5 @@
Allocator_Kind :: enum
Null
Arena
Heap = Arena

View File

@@ -7,6 +7,8 @@
#include "ccodegen.cpp" #include "ccodegen.cpp"
/* /*
-------------------------------------------------------------------------------
2022.05.28 - On lambda expressions 2022.05.28 - On lambda expressions
I think it's not wise to add the multiline lambda expressions I think it's not wise to add the multiline lambda expressions
As is the case with python it would require new alternative syntax. As is the case with python it would require new alternative syntax.
@@ -18,12 +20,14 @@ in a language to solve something that is a minor inconvenience,
second of all it turned out to be kind of bad, maybe if it would be more second of all it turned out to be kind of bad, maybe if it would be more
complicated then it would be ok but it implies that you have to semicolon end complicated then it would be ok but it implies that you have to semicolon end
a lot of thing unintuitively. a lot of thing unintuitively.
//
Probably single line lambdas should be ok. Currently braces turn off indentation Probably single line lambdas should be ok. Currently braces turn off indentation
awareness. There might be something you can do by trying to turn that on awareness. There might be something you can do by trying to turn that on
problem is that complicates parsing a lot cause you have to account for multiple problem is that complicates parsing a lot cause you have to account for multiple
indent styles, which means error messages become bad. indent styles, which means error messages become bad.
-------------------------------------------------------------------------------
2022.05.30 - On constructors and compound expressions 2022.05.30 - On constructors and compound expressions
I unified the compound expression syntax (Type){} with function call syntax Type(). I unified the compound expression syntax (Type){} with function call syntax Type().
It's differentiating on whether you used type. I think there is a benefit to the language It's differentiating on whether you used type. I think there is a benefit to the language
@@ -33,6 +37,7 @@ and variants. having the idea of compounds doing one thing is reassuring I think
You can always do a constructor by writing a function with lower case type if you want that. You can always do a constructor by writing a function with lower case type if you want that.
For now I don't thing it should be overloadable. For now I don't thing it should be overloadable.
-------------------------------------------------------------------------------
@todo @todo
[ ] - Enums [ ] - Enums
@@ -40,11 +45,13 @@ For now I don't thing it should be overloadable.
[ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree [ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree
[ ] - Access through struct names to constants Arena.CONSTANT [ ] - Access through struct names to constants Arena.CONSTANT
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative [ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
[ ] - Write up on order independent declarations
[ ] - For loop [ ] - For loop
[ ] - Switch [ ] - Switch
[ ] - Lexer: Need to insert scope endings when hitting End of file [ ] - Lexer: Need to insert scope endings when hitting End of file
[ ] - Add single line lambda expressions [ ] - Add single line lambda expressions
@donzo @donzo
[x] - Struct calls [x] - Struct calls
[x] - Default values in calls [x] - Default values in calls
@@ -76,7 +83,8 @@ int main(){
String result = {}; String result = {};
// result = compile_file("order1.kl"_s); // result = compile_file("order1.kl"_s);
// result = compile_file("lambdas.kl"_s); // result = compile_file("lambdas.kl"_s);
result = compile_file("order2.kl"_s); // result = compile_file("order2.kl"_s);
result = compile_file("enums.kl"_s);
// result = compile_file("globals.kl"_s); // result = compile_file("globals.kl"_s);
printf("%s", result.str); printf("%s", result.str);

View File

@@ -100,6 +100,8 @@ enum Ast_Kind: U32{
AST_BLOCK, AST_BLOCK,
AST_LAMBDA, AST_LAMBDA,
AST_LAMBDA_ARG, AST_LAMBDA_ARG,
AST_ENUM,
AST_ENUM_MEMBER,
AST_STRUCT, AST_STRUCT,
AST_CONST, AST_CONST,
AST_VAR, AST_VAR,
@@ -112,7 +114,8 @@ enum{
AST_BINDING = 4, AST_BINDING = 4,
AST_AGGREGATE = 8, AST_AGGREGATE = 8,
AST_ATOM = 16, AST_ATOM = 16,
AST_ITEM_INCLUDED = 32, AST_AGGREGATE_CHILD = 32,
AST_ITEM_INCLUDED = 64,
}; };
struct Ast{ struct Ast{
@@ -191,11 +194,6 @@ struct Ast_If: Ast{
Array<Ast_If_Node *> ifs; Array<Ast_If_Node *> ifs;
}; };
struct Ast_Enum : Ast{
Ast_Expr *typespec;
Array<Ast_Init *> children;
};
struct Ast_Lambda_Arg: Ast_Expr{ struct Ast_Lambda_Arg: Ast_Expr{
Intern_String name; Intern_String name;
Ast_Expr *typespec; Ast_Expr *typespec;
@@ -224,18 +222,29 @@ struct Ast_Var: Ast_Named{
struct Ast_Const; struct Ast_Const;
struct Ast_Resolved_Type; struct Ast_Resolved_Type;
struct Ast_Struct: Ast_Expr{ struct Ast_Struct: Ast{
// Required to be Ast_Struct or Ast_Var or Ast_Const // Required to be Ast_Struct or Ast_Var or Ast_Const
Array<Ast_Var *> members; Array<Ast_Var *> members;
Array<Ast_Const *> const_members; Array<Ast_Const *> const_members;
Ast_Resolved_Type *type; Ast_Resolved_Type *type;
}; };
struct Ast_Enum_Member: Ast{
Intern_String name;
Ast_Expr *value;
};
struct Ast_Enum: Ast{
Ast_Expr *typespec;
Array<Ast_Enum_Member *> members;
};
struct Ast_Const: Ast_Named{ struct Ast_Const: Ast_Named{
union{ union{
Ast *ast; Ast *ast;
Ast_Expr *value; Ast_Expr *value;
Ast_Struct *agg; Ast_Struct *agg;
Ast_Enum *enu;
}; };
}; };
@@ -421,12 +430,32 @@ ast_init(Token *pos, Token_Kind op, Ast_Atom *ident, Ast_Expr *expr){
function Ast_Array * function Ast_Array *
ast_array(Token *pos, Ast_Expr *expr){ ast_array(Token *pos, Ast_Expr *expr){
AST_NEW(Array, ARRAY, pos, AST_EXPR); AST_NEW(Array, ARRAY, pos, AST_EXPR);
result->flags = AST_EXPR;
result->expr = expr; result->expr = expr;
result->expr->parent = result; result->expr->parent = result;
return result; return result;
} }
function Ast_Enum_Member *
ast_enum_member(Token *pos, Intern_String name, Ast_Expr *default_value){
AST_NEW(Enum_Member, ENUM_MEMBER, pos, AST_AGGREGATE_CHILD);
result->name = name;
result->value = default_value;
if(result->value) result->value->parent = result;
return result;
}
function Ast_Enum *
ast_enum(Token *pos, Ast_Expr *typespec, Array<Ast_Enum_Member *> members){
AST_NEW(Enum, ENUM, pos, AST_AGGREGATE);
result->members = members.tight_copy(pctx->perm);
result->typespec = typespec;
if(result->typespec) result->typespec->parent = result;
For(result->members){
it->parent = result;
}
return result;
}
function Ast_Struct * function Ast_Struct *
ast_struct(Token *pos, Array<Ast_Var *> members, Array<Ast_Const *> const_members){ ast_struct(Token *pos, Array<Ast_Var *> members, Array<Ast_Const *> const_members){
AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE); AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE);
@@ -461,9 +490,8 @@ ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
function Ast_Const * function Ast_Const *
ast_const(Token *pos, Intern_String name, Ast_Expr *value){ ast_const(Token *pos, Intern_String name, Ast_Expr *value){
assert(is_flag_set(value->flags, AST_AGGREGATE) || is_flag_set(value->flags, AST_EXPR) );
AST_NEW(Const, CONST, pos, AST_BINDING); AST_NEW(Const, CONST, pos, AST_BINDING);
assert(value->kind == AST_STRUCT || is_flag_set(value->flags, AST_EXPR));
result->value = value; result->value = value;
result->name = name; result->name = name;
result->value->parent = result; result->value->parent = result;

View File

@@ -419,6 +419,7 @@ parse_struct(Token *pos){
do{ do{
Token *token = token_get(); Token *token = token_get();
Ast_Named *named = parse_named(false); Ast_Named *named = parse_named(false);
named->flags = set_flag(named->flags, AST_AGGREGATE_CHILD);
if(!named) parsing_error(token, "Failed to parse struct member"); if(!named) parsing_error(token, "Failed to parse struct member");
if(named->kind == AST_CONST){ if(named->kind == AST_CONST){
members_const.add((Ast_Const *)named); members_const.add((Ast_Const *)named);
@@ -434,6 +435,25 @@ parse_struct(Token *pos){
return result; return result;
} }
function Ast_Enum *
parse_enum(Token *pos){
Scratch scratch;
Array<Ast_Enum_Member *> members = {scratch};
Ast_Expr *typespec = parse_optional_type();
token_match(OPEN_SCOPE);
do{
Token *name = token_expect(TK_Identifier);
Ast_Expr *value = parse_assign_expr();
Ast_Enum_Member *member = ast_enum_member(name, name->intern_val, value);
members.add(member);
}while(token_match(SAME_SCOPE));
token_expect(CLOSE_SCOPE);
Ast_Enum *result = ast_enum(pos, typespec, members);
return result;
}
function Ast_Named * function Ast_Named *
parse_named(B32 is_global){ parse_named(B32 is_global){
Ast_Named *result = 0; Ast_Named *result = 0;
@@ -448,7 +468,12 @@ parse_named(B32 is_global){
Token *struct_pos = token_get(); Token *struct_pos = token_get();
if(token_match_keyword(keyword_struct)){ if(token_match_keyword(keyword_struct)){
Ast_Struct *struct_val = parse_struct(struct_pos); Ast_Struct *struct_val = parse_struct(struct_pos);
result = ast_const(name, name->intern_val, struct_val); result = ast_const(name, name->intern_val, (Ast_Expr *)struct_val);
}
else if(token_match_keyword(keyword_enum)){
Ast_Enum *enum_val = parse_enum(struct_pos);
result = ast_const(name, name->intern_val, (Ast_Expr *)enum_val);
} }
// parse constant expression // parse constant expression

View File

@@ -163,6 +163,19 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
return result; return result;
} }
function Ast_Resolved_Type *
type_enum(Ast_Enum *ast){
Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
if(!type) {
type = type_int;
}
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align);
result->base = type;
result->ast = ast;
return result;
}
function Ast_Resolved_Type * function Ast_Resolved_Type *
type_incomplete(Ast *ast){ type_incomplete(Ast *ast){
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);

View File

@@ -11,6 +11,9 @@ arena := Arena(
// constant_inside = 10, // constant_inside = 10,
) )
// lambda_value := (val: int) // What to do with this???
// return
Arena :: struct Arena :: struct
// arena: Arena // arena: Arena
next: *Arena next: *Arena

View File

@@ -42,12 +42,13 @@ enum{
AST_CAN_BE_NULL = 1 AST_CAN_BE_NULL = 1
}; };
struct Typecheck_Ctx{ struct Typecheck_Ctx{ // @todo
Ast_Resolved_Type *required_type; Ast_Resolved_Type *required_type;
Sym *const_sym; Sym *const_sym;
B32 expr_can_be_null; B32 expr_can_be_null;
}; };
function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL);
function Sym *resolve_name(Token *pos, Intern_String name); function Sym *resolve_name(Token *pos, Intern_String name);
function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *const_sym = 0); function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *const_sym = 0);
function Operand resolve_binding(Ast *ast, Sym *sym = 0); function Operand resolve_binding(Ast *ast, Sym *sym = 0);
@@ -166,7 +167,7 @@ sym_insert_builtins(){
} }
function Ast_Resolved_Type * function Ast_Resolved_Type *
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL){ resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
if(ast_can_be_null && ast == 0) return 0; if(ast_can_be_null && ast == 0) return 0;
Operand resolved = resolve_expr(ast); Operand resolved = resolve_expr(ast);
if(resolved.type != type_type) parsing_error(ast->pos, "Expected [Type] got instead %s", resolved.type->kind); if(resolved.type != type_type) parsing_error(ast->pos, "Expected [Type] got instead %s", resolved.type->kind);
@@ -255,6 +256,27 @@ operand(Sym *sym){
return result; return result;
} }
function Operand
operand_type(Ast_Resolved_Type *type){
Operand result = {type_type, true};
result.type_val = type;
return result;
}
function Operand
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
Operand op = resolve_expr(expr);
if(expr == 0 && ast_can_be_null){
return op;
}
else if(expr == 0) parsing_error(expr->pos, "This field cannot be null");
if(!op.is_const) parsing_error(expr->pos, "Expected a const value");
if(op.type != type_int) parsing_error(expr->pos, "Expected a constant integer");
return op;
}
function Operand function Operand
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
if(!ast) return {}; // @todo: add option for better error prevention if(!ast) return {}; // @todo: add option for better error prevention
@@ -308,6 +330,31 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
BREAK(); BREAK();
} }
CASE(ENUM, Enum){
Ast_Resolved_Type *type = type_enum(node);
S64 scope_index = scope_open();
S64 value = 0;
For(node->members){
Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
if(op.type){
value = op.int_val + 1;
}
else{
op.type = type_int;
op.int_val = value++;
}
Sym *arg_sym = sym_new_resolved(SYM_CONST, it->name, op.type, op.value, it);
sym_insert(arg_sym);
}
scope_close(scope_index);
return operand_type(type);
BREAK();
}
CASE(LAMBDA, Lambda){ CASE(LAMBDA, Lambda){
// @note: first resolve type of lambda // @note: first resolve type of lambda
Scratch scratch; Scratch scratch;