diff --git a/ccodegen.cpp b/ccodegen.cpp index 1de4c8e..4aad217 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -245,8 +245,8 @@ gen_ast(Ast *ast){ Sym *sym = resolved_get(node); if(sym->type->kind == TYPE_Lambda){ - if(node->expr->kind == AST_LAMBDA){ - Ast_Lambda *lambda = (Ast_Lambda *)node->expr; + if(node->value->kind == AST_LAMBDA){ + Ast_Lambda *lambda = (Ast_Lambda *)node->value; gen("static "); Ast_Resolved_Type *ret = resolved_type_get(lambda->ret); gen_simple_decl(ret, node->name); @@ -267,7 +267,7 @@ gen_ast(Ast *ast){ else{ gen_simple_decl(sym->type, node->name); gen(" = "); - gen_expr(node->expr); + gen_expr((Ast_Expr *)node->value); gen(";"); } } diff --git a/main.cpp b/main.cpp index 8d8d87b..1936598 100644 --- a/main.cpp +++ b/main.cpp @@ -7,8 +7,32 @@ #include "new_resolve.cpp" #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. +// The idea was to imply that the whitespace significant syntax is just +// inserting '{' '}' ';' automatically and if you decide to write a brace +// it stops being whitespace significant and you can type everything with semicolons and braces +// Problem is first of all it's kind of weird to have a completly different syntax +// 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. + + /// @todo /// [x] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int +/// [ ] - Add single line lambda expressions/ +/// [ ] - Think about compound expressions, unify with calls - maybe Thing(a=1) instead of Thing{a=1} +/// [ ] - Structs +/// [ ] - Enums +/// [ ] - For loop +/// [ ] - Switch int main(){ @@ -23,8 +47,8 @@ int main(){ test_intern_table(); lex_test(); - String result = compile_file("globals.kl"_s); - // String result = compile_file("lambdas.kl"_s); + // String result = compile_file("globals.kl"_s); + String result = compile_file("structs.kl"_s); // String result = compile_file("order_independent_globals.kl"_s); printf("%s", result.str); diff --git a/new_ast.cpp b/new_ast.cpp index 94e7a0f..bc117e6 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -100,13 +100,14 @@ enum Ast_Kind{ AST_BLOCK, AST_LAMBDA, AST_LAMBDA_ARG, + AST_STRUCT, AST_CONST, AST_VAR, +}; - AST_TYPESPEC_IDENT, - AST_TYPESPEC_POINTER, - AST_TYPESPEC_ARRAY, - AST_TYPESPEC_LAMBDA +typedef U32 Ast_Flag; +enum{ + AST_EXPR = 1, }; struct Ast{ @@ -115,11 +116,12 @@ struct Ast{ Ast_Kind kind; Ast *parent; + Ast_Flag flags; // @todo? // bool is_atom: 1; // bool is_stmt: 1; - // bool is_expr: 1; // bool is_decl: 1; + // bool is_expr: 1; // bool is_named: 1; }; @@ -211,6 +213,12 @@ struct Ast_Array: Ast_Expr{ Ast_Expr *expr; }; +struct Ast_Struct: Ast{ + // Required to be Ast_Struct or Ast_Var or Ast_Const + Array members; + +}; + struct Ast_Named:Ast{ Intern_String name; }; @@ -221,7 +229,7 @@ struct Ast_Var: Ast_Named{ }; struct Ast_Const: Ast_Named{ - Ast_Expr *expr; + Ast *value; }; struct Ast_Package:Ast{ @@ -240,22 +248,25 @@ struct Ast_Package:Ast{ result->id = ++pctx->unique_ids function Ast_Atom * -ast_str(Token *pos, Intern_String string){ +ast_str(Token *pos, Intern_String string, Ast_Flag flags = 0){ AST_NEW(Atom, STR, pos); + result->flags = flags; result->intern_val = string; return result; } function Ast_Atom * -ast_ident(Token *pos, Intern_String string){ +ast_ident(Token *pos, Intern_String string, Ast_Flag flags = 0){ AST_NEW(Atom, IDENT, pos); + result->flags = flags; result->intern_val = string; return result; } function Ast_Atom * -ast_int(Token *pos, S64 integer){ +ast_int(Token *pos, S64 integer, Ast_Flag flags){ AST_NEW(Atom, INT, pos); + result->flags = flags; result->int_val = integer; return result; } @@ -263,6 +274,7 @@ ast_int(Token *pos, S64 integer){ function Ast_Expr * ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){ AST_NEW(Binary, BINARY, op); + result->flags = AST_EXPR; result->op = op->kind; result->left = left; result->right = right; @@ -274,6 +286,7 @@ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){ function Ast_Compound * ast_expr_compound(Token *pos, Ast_Expr *typespec, Array exprs){ AST_NEW(Compound, COMPOUND, pos); + result->flags = AST_EXPR; result->typespec = typespec; result->exprs = exprs.tight_copy(pctx->perm); if(result->typespec) result->typespec->parent = result; @@ -284,6 +297,7 @@ ast_expr_compound(Token *pos, Ast_Expr *typespec, Array exp function Ast_Compound_Item * ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Atom *name, Ast_Expr *item){ AST_NEW(Compound_Item, COMPOUND_ITEM, pos); + result->flags = AST_EXPR; result->name = name; result->index = index; result->item = item; @@ -296,6 +310,7 @@ ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Atom *name, Ast_Expr *it function Ast_Expr * ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Expr *typespec){ AST_NEW(Cast, CAST, pos); + result->flags = AST_EXPR; result->expr = expr; result->typespec = typespec; expr->parent = result; @@ -306,6 +321,7 @@ ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Expr *typespec){ function Ast_Expr * ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){ AST_NEW(Unary, UNARY, pos); + result->flags = AST_EXPR; result->expr = expr; result->op = op; expr->parent = result; @@ -315,6 +331,7 @@ ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){ function Ast_Expr * ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){ AST_NEW(Index, INDEX, pos); + result->flags = AST_EXPR; result->expr = expr; result->index = index; expr->parent = result; @@ -325,6 +342,7 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){ function Ast_Lambda * ast_lambda(Token *pos, Array params, Ast_Expr *ret, Ast_Block *block){ AST_NEW(Lambda, LAMBDA, pos); + result->flags = AST_EXPR; result->args = params.tight_copy(pctx->perm); result->block = block; result->ret = ret; @@ -339,6 +357,7 @@ ast_lambda(Token *pos, Array params, Ast_Expr *ret, Ast_Block function Ast_Lambda_Arg * ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Expr *typespec){ AST_NEW(Lambda_Arg, LAMBDA_ARG, pos); + result->flags = AST_EXPR; result->name = name; result->typespec = typespec; result->typespec->parent = result; @@ -387,11 +406,23 @@ 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); + result->flags = AST_EXPR; result->expr = expr; result->expr->parent = result; return result; } +function Ast_Struct * +ast_struct(Token *pos, Array members){ + AST_NEW(Struct, STRUCT, pos); + result->members = members.tight_copy(pctx->perm); + For(result->members) { + assert(it[0]->kind == AST_VAR || it[0]->kind == AST_CONST || it[0]->kind == AST_STRUCT); + it[0]->parent = result; + } + return result; +} + //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- @@ -407,11 +438,13 @@ 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 *expr){ +ast_const(Token *pos, Intern_String name, Ast *value){ AST_NEW(Const, CONST, pos); - result->expr = expr; + + assert(value->kind == AST_STRUCT || is_flag_set(value->flags, AST_EXPR)); + result->value = value; result->name = name; - result->expr->parent = result; + result->value->parent = result; return result; } diff --git a/new_parse.cpp b/new_parse.cpp index 279bed6..df43d92 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -281,9 +281,9 @@ parse_lambda(Token *token, B32 is_typespec = false){ function Ast_Expr * null_denotation(Token *token){ switch(token->kind){ - case TK_StringLit : return ast_str(token, token->intern_val); - case TK_Identifier : return ast_ident(token, token->intern_val); - case TK_Integer : return ast_int(token, token->int_val); + case TK_StringLit : return ast_str(token, token->intern_val, AST_EXPR); + case TK_Identifier : return ast_ident(token, token->intern_val, AST_EXPR); + case TK_Integer : return ast_int(token, token->int_val, AST_EXPR); case TK_Pointer : return ast_expr_unary(token, TK_Pointer, parse_expr()); case TK_Dereference: return ast_expr_unary(token, TK_Dereference, parse_expr()); case TK_OpenBracket: { @@ -386,6 +386,23 @@ parse_assign_expr(){ return result; } +function Ast_Struct * +parse_struct(Token *pos){ + Scratch scratch; + Array members = {scratch}; + + token_match(OPEN_SCOPE); + do{ + Token *token = token_get(); + Ast_Named *named = parse_named(false); + if(!named) parsing_error(token, "Failed to parse struct member"); + }while(token_match(SAME_SCOPE)); + token_expect(CLOSE_SCOPE); + + Ast_Struct *result = ast_struct(pos, members); + return result; +} + function Ast_Named * parse_named(B32 is_global){ Ast_Named *result = 0; @@ -393,10 +410,24 @@ parse_named(B32 is_global){ if(token_is(TK_Identifier)){ if(is_global && pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented"); Token *name = token_next(); - if(token_match(TK_DoubleColon)){ // Constant - Ast_Expr *expr = parse_expr(); - result = ast_const(name, name->intern_val, expr); + + // @note: parse constant + if(token_match(TK_DoubleColon)){ + // parse struct binding + 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); + } + + // parse constant expression + else{ + Ast_Expr *expr = parse_expr(); + result = ast_const(name, name->intern_val, expr); + } } + + // @note: parse variable else if(token_match(TK_Colon)){ Ast_Expr *typespec = 0; Ast_Expr *expr = 0; diff --git a/new_resolve.cpp b/new_resolve.cpp index b089444..d939ac8 100644 --- a/new_resolve.cpp +++ b/new_resolve.cpp @@ -504,7 +504,7 @@ eval_decl(Ast *ast, Sym *sym){ } Ast_Begin(AST_CONST, Ast_Const){ - Operand expr = eval_expr(node->expr, 0, sym); + Operand expr = eval_expr((Ast_Expr *)node->value, 0, sym); if(!expr.type) parsing_error(node->pos, "Constant value without expression"); if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression"); return expr; @@ -519,8 +519,8 @@ function Ast_Lambda * ast_get_lambda(Ast *ast){ if(ast->kind == AST_CONST){ auto ast_const = (Ast_Const *)ast; - if(ast_const->expr){ - auto ast_expr = ast_const->expr; + if(ast_const->value){ + auto ast_expr = ast_const->value; if(ast_expr->kind == AST_LAMBDA){ return (Ast_Lambda *)ast_expr; } diff --git a/order_independent_globals.kl b/order_independent_globals.kl index fec4a15..0f4fa99 100644 --- a/order_independent_globals.kl +++ b/order_independent_globals.kl @@ -13,6 +13,8 @@ unifying the call expression and compound expression seems more unified and better for coherence but more abigous and probably harder to implement +value :: call((thing: int): int thing += 1; return thing, ) + */ diff --git a/structs.kl b/structs.kl new file mode 100644 index 0000000..e69de29