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_ARRAY: gen_simple_decl_prefix(ast->base); break;
case TYPE_LAMBDA:break;
case TYPE_ENUM:
case TYPE_STRUCT: {
auto constant = (Ast_Const *)ast->ast->parent;
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_ARRAY: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
case TYPE_LAMBDA:break;
case TYPE_STRUCT:break;
case TYPE_ENUM: case TYPE_STRUCT:break;
invalid_default_case;
}
}
@@ -323,7 +324,28 @@ gen_ast(Ast *ast){
genln("};");
}
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{

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"
/*
-------------------------------------------------------------------------------
2022.05.28 - On 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.
@@ -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
complicated then it would be ok but it implies that you have to semicolon end
a lot of thing unintuitively.
//
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
problem is that complicates parsing a lot cause you have to account for multiple
indent styles, which means error messages become bad.
-------------------------------------------------------------------------------
2022.05.30 - On constructors and compound expressions
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
@@ -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.
For now I don't thing it should be overloadable.
-------------------------------------------------------------------------------
@todo
[ ] - 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
[ ] - 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
[ ] - Write up on order independent declarations
[ ] - For loop
[ ] - Switch
[ ] - Lexer: Need to insert scope endings when hitting End of file
[ ] - Add single line lambda expressions
@donzo
[x] - Struct calls
[x] - Default values in calls
@@ -76,7 +83,8 @@ int main(){
String result = {};
// result = compile_file("order1.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);
printf("%s", result.str);

View File

@@ -100,6 +100,8 @@ enum Ast_Kind: U32{
AST_BLOCK,
AST_LAMBDA,
AST_LAMBDA_ARG,
AST_ENUM,
AST_ENUM_MEMBER,
AST_STRUCT,
AST_CONST,
AST_VAR,
@@ -112,7 +114,8 @@ enum{
AST_BINDING = 4,
AST_AGGREGATE = 8,
AST_ATOM = 16,
AST_ITEM_INCLUDED = 32,
AST_AGGREGATE_CHILD = 32,
AST_ITEM_INCLUDED = 64,
};
struct Ast{
@@ -191,11 +194,6 @@ struct Ast_If: Ast{
Array<Ast_If_Node *> ifs;
};
struct Ast_Enum : Ast{
Ast_Expr *typespec;
Array<Ast_Init *> children;
};
struct Ast_Lambda_Arg: Ast_Expr{
Intern_String name;
Ast_Expr *typespec;
@@ -224,18 +222,29 @@ struct Ast_Var: Ast_Named{
struct Ast_Const;
struct Ast_Resolved_Type;
struct Ast_Struct: Ast_Expr{
struct Ast_Struct: Ast{
// Required to be Ast_Struct or Ast_Var or Ast_Const
Array<Ast_Var *> members;
Array<Ast_Const *> const_members;
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{
union{
Ast *ast;
Ast_Expr *value;
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 *
ast_array(Token *pos, Ast_Expr *expr){
AST_NEW(Array, ARRAY, pos, AST_EXPR);
result->flags = AST_EXPR;
result->expr = expr;
result->expr->parent = 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 *
ast_struct(Token *pos, Array<Ast_Var *> members, Array<Ast_Const *> const_members){
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 *
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);
assert(value->kind == AST_STRUCT || is_flag_set(value->flags, AST_EXPR));
result->value = value;
result->name = name;
result->value->parent = result;

View File

@@ -419,6 +419,7 @@ parse_struct(Token *pos){
do{
Token *token = token_get();
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->kind == AST_CONST){
members_const.add((Ast_Const *)named);
@@ -434,6 +435,25 @@ parse_struct(Token *pos){
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 *
parse_named(B32 is_global){
Ast_Named *result = 0;
@@ -448,7 +468,12 @@ parse_named(B32 is_global){
Token *struct_pos = token_get();
if(token_match_keyword(keyword_struct)){
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

View File

@@ -163,6 +163,19 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
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 *
type_incomplete(Ast *ast){
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);

View File

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

View File

@@ -42,12 +42,13 @@ enum{
AST_CAN_BE_NULL = 1
};
struct Typecheck_Ctx{
struct Typecheck_Ctx{ // @todo
Ast_Resolved_Type *required_type;
Sym *const_sym;
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 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);
@@ -166,7 +167,7 @@ sym_insert_builtins(){
}
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;
Operand resolved = resolve_expr(ast);
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;
}
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
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
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();
}
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){
// @note: first resolve type of lambda
Scratch scratch;