From 98d2389c9f5714eb026cb08e59a815b5fa3cd15f Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 31 May 2022 22:52:56 +0200 Subject: [PATCH] Cleanup --- main.cpp | 11 ++-- new_ast.cpp | 12 ++-- new_lex.cpp | 61 +++----------------- new_parse.cpp | 33 ++++++----- typecheck.cpp | 154 +++++++++++++++++++++++++++----------------------- 5 files changed, 119 insertions(+), 152 deletions(-) diff --git a/main.cpp b/main.cpp index f2c4a4f..58d8e37 100644 --- a/main.cpp +++ b/main.cpp @@ -32,15 +32,14 @@ For now I don't thing it should be overloadable. ------------------------------------------------------------------------------- @todo -[ ] - For loop -[ ] - Pass statement -[ ] - More operators [ ] - Init statements +[ ] - More operators +[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression +[ ] - More for loop variations [ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree [ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative [ ] - Write up on order independent declarations [ ] - Switch -[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression [ ] - More basic types [ ] - Array of inferred size [ ] - Lexer: Need to insert scope endings when hitting End of file @@ -52,10 +51,12 @@ For now I don't thing it should be overloadable. @donzo [x] - Access through struct names to constants Arena.CONSTANT [x] - Enums +[x] - Initial for loop [x] - Enum . access to values [x] - Struct calls [x] - Default values in calls [x] - Resolving calls with default values +[x] - Pass statement [x] - Resolving calls with named args, with indexed args [x] - Structs [x] - Struct field access @@ -63,7 +64,6 @@ For now I don't thing it should be overloadable. [x] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int [x] - Initial order independence algorithm [x] - Think about compound expressions, unify with calls - maybe Thing(a=1) instead of Thing{a=1} - */ #include "base.cpp" @@ -85,7 +85,6 @@ int main(){ test_array(); test_string_builder(); test_intern_table(); - lex_test(); String result = {}; result = compile_file("globals.kl"_s); diff --git a/new_ast.cpp b/new_ast.cpp index 687a02e..8f7a867 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -271,22 +271,22 @@ struct Ast_Package:Ast{ result->id = ++pctx->unique_ids function Ast_Atom * -ast_str(Token *pos, Intern_String string, Ast_Flag flags = 0){ - AST_NEW(Atom, STR, pos, AST_ATOM | flags); +ast_str(Token *pos, Intern_String string){ + AST_NEW(Atom, STR, pos, AST_ATOM | AST_EXPR); result->intern_val = string; return result; } function Ast_Atom * -ast_ident(Token *pos, Intern_String string, Ast_Flag flags = 0){ - AST_NEW(Atom, IDENT, pos, AST_ATOM | flags); +ast_ident(Token *pos, Intern_String string){ + AST_NEW(Atom, IDENT, pos, AST_ATOM | AST_EXPR); result->intern_val = string; return result; } function Ast_Atom * -ast_int(Token *pos, S64 integer, Ast_Flag flags = 0){ - AST_NEW(Atom, INT, pos, AST_ATOM | flags); +ast_int(Token *pos, S64 integer){ + AST_NEW(Atom, INT, pos, AST_ATOM | AST_EXPR); result->int_val = integer; return result; } diff --git a/new_lex.cpp b/new_lex.cpp index 7f241a5..9a740fb 100644 --- a/new_lex.cpp +++ b/new_lex.cpp @@ -51,6 +51,7 @@ enum Token_Kind{ TK_Colon, TK_Assign, + TK_ColonAssign, TK_DivAssign, TK_MulAssign, TK_ModAssign, @@ -131,6 +132,8 @@ struct Lexer{ S64 token_iter; }; +force_inline B32 token_is_assign(Token *token){return token->kind >= TK_FirstAssign && token->kind <= TK_LastAssign;} + function U8 lexc(Lex_Stream *s){ return s->stream.str[s->iter]; @@ -507,6 +510,10 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ lex_advance(s); t.kind = TK_DoubleColon; } + else if(lexc(s) == '='){ + lex_advance(s); + t.kind = TK_ColonAssign; + } else { t.kind = TK_Colon; } @@ -630,59 +637,6 @@ lex_stream(Allocator *token_string_arena, Allocator *map_allocator, String istre return result; } -function void -lex_test(){ - Scratch scratch; - String test = "Keyword //R\n 18446744073709551616\n {}\n)(@?&+-....->,:::/**/\"Thing\" Thingy" - "\"Test_Meme\"+=-===42524 4294967295 18446744073709551615" - "for if while switch :="_s; - - Array keywords = {scratch}; - keywords.add("Keyword"_s); - keywords.add("for"_s); - keywords.add("if"_s); - keywords.add("while"_s); - keywords.add("switch"_s); - - Lexer lexer = lex_make(scratch, scratch); - lex_set_keywords(&lexer, keywords); - lex_restream(&lexer, test, "Test1"_s); - Array arr = lexer.tokens; - - Token_Kind kind[] = { - SAME_SCOPE, - TK_Keyword, OPEN_SCOPE, TK_Error, OPEN_SCOPE, TK_OpenBrace,TK_CloseBrace,CLOSE_SCOPE, CLOSE_SCOPE, SAME_SCOPE, TK_CloseParen,TK_OpenParen, - TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub, - TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon, - TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign, - TK_Equals, TK_Integer, TK_Integer, TK_Integer, - TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, - TK_Colon, TK_Assign, TK_End - }; - String strs[] = { - ""_s, "Keyword"_s, ""_s, "18446744073709551616"_s, ""_s, "{"_s,"}"_s, ""_s, ""_s, ""_s, ")"_s, "("_s, - "@"_s,"?"_s,"&"_s,"+"_s,"-"_s, - "..."_s,"."_s,"->"_s,","_s,"::"_s,":"_s, - "Thing"_s,"Thingy"_s,"Test_Meme"_s, "+="_s,"-="_s, - "=="_s,"42524"_s,"4294967295"_s,"18446744073709551615"_s, - "for"_s, "if"_s, "while"_s, "switch"_s, ":"_s, "="_s, ""_s, - }; - U64 vals[] = { - 42524, 4294967295, 18446744073709551615llu - }; - - int ui = 0; - S32 i = 0; - For(arr){ - assert(it.kind == kind[i]); - assert(string_compare(it.string, strs[i])); - if(it.kind == TK_Integer){ - assert(it.int_val == vals[ui++]); - } - i++; - } -} - //----------------------------------------------------------------------------- // Token metadata //----------------------------------------------------------------------------- @@ -706,6 +660,7 @@ token_kind_string(Token_Kind kind){ case TK_CloseBrace: return "}"_s; case TK_OpenBracket: return "["_s; case TK_CloseBracket: return "]"_s; + case TK_ColonAssign: return ":="_s; case TK_Comma: return ","_s; case TK_Pound: return "#"_s; case TK_Question: return "?"_s; diff --git a/new_parse.cpp b/new_parse.cpp index faaac64..8428fe6 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -138,14 +138,12 @@ function Ast_Expr *parse_expr(S64 rbp = 0); function Ast_Expr * parse_init_stmt(Ast_Expr *expr){ Token *token = token_get(); - if(token_match(TK_Colon)){ - if(expr->kind != AST_IDENT) parsing_error(token, "Failed to parse init stmt, expected left of [:] to be a token of kind [Identifier]"); - if(token_match(TK_Assign)){ - Ast_Expr *value = parse_expr(); - Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token); - return result; - } - else not_implemented; + if(token_is_assign(token)){ + token_next(); + Ast_Expr *value = parse_expr(); + Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token); + result->flags = set_flag(result->flags, AST_STMT); + return result; } return 0; } @@ -311,9 +309,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, 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_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_Pointer : return ast_expr_unary(token, TK_Pointer, parse_expr()); case TK_Dereference: return ast_expr_unary(token, TK_Dereference, parse_expr()); @@ -505,14 +503,15 @@ parse_named(B32 is_global){ } } + else if(token_match(TK_ColonAssign)){ + Ast_Expr *expr = parse_expr(); + result = ast_var(name, 0, name->intern_val, expr); + } + // @note: parse variable else if(token_match(TK_Colon)){ - Ast_Expr *typespec = 0; - Ast_Expr *expr = 0; - if(!token_is(TK_Assign)) typespec = parse_expr(); - if(token_match(TK_Assign)) expr = parse_expr(); - if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value"); - + Ast_Expr *typespec = typespec = parse_expr(); + Ast_Expr *expr = parse_assign_expr(); result = ast_var(name, typespec, name->intern_val, expr); } else{ diff --git a/typecheck.cpp b/typecheck.cpp index 387ec3f..7fb4f46 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -65,7 +65,7 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ CASE(BINARY, Binary){ switch(node->op){ - case TK_Colon:{ + case TK_ColonAssign:{ // Operand left = resolve_expr(node->left); // needs to be lvalue Operand right = resolve_expr(node->right); assert(node->left->kind == AST_IDENT); @@ -134,9 +134,54 @@ _rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){ } #define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym) +function Operand +resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ + Scratch scratch; + Ast_Resolved_Type *lambda_type = 0; + Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret); + Array args = {scratch}; + For(lambda->args){ + Operand type = resolve_expr(it->typespec); + if(type.type != type_type) parsing_error(it->pos, "Required expression of kind [type]"); + Operand default_value = resolve_expr(it->default_value, type.type_val); + if(default_value.type && default_value.type != type.type_val) parsing_error(it->pos, "Default value type and type declaration differ"); + args.add(type.type_val); + } + + lambda_type = type_lambda(lambda, ret_type, args); + sym_type(lambda, lambda_type); + Operand result = operand_type(lambda_type); + + // @note: top level lambda needs to get marked as resolved + // so that the cyclic dependency wont trigger + if(sym){ + sym->type = lambda_type; + sym->state = SYM_RESOLVED; + } + + // @todo: We also need to make sure there is a return value when ret type is not void + // @note: then try resolving the block of lambda + if(lambda->block){ + S64 scope_index = scope_open(); + For(lambda->args){ + S64 i = lambda->args.get_index(&it); + Ast_Resolved_Type *type = args[i]; + sym_insert(SYM_VAR, it->name, type, {}, it); + } + For(lambda->block->stmts){ + resolve_stmt(it, ret_type); + } + scope_close(scope_index); + result.type = lambda_type; + } + + return result; +} + function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){ if(!ast) return {}; // @todo: add option for better error prevention + assert(is_flag_set(ast->flags, AST_EXPR)); switch(ast->kind){ CASE(INT, Atom){ @@ -188,70 +233,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res 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_insert(SYM_CONST, it->name, op.type, op.value, it); - } - scope_close(scope_index); - - return operand_type(type); - BREAK(); - } - CASE(LAMBDA, Lambda){ - // @note: first resolve type of lambda so recursive lambdas work - Scratch scratch; - Ast_Resolved_Type *lambda_type = 0; - Ast_Resolved_Type *ret_type = resolve_typespec(node->ret); - Array args = {scratch}; - For(node->args){ - Operand type = resolve_expr(it->typespec); - if(type.type != type_type) parsing_error(it->pos, "Required expression of kind [type]"); - Operand default_value = resolve_expr(it->default_value, type.type_val); - if(default_value.type && default_value.type != type.type_val) parsing_error(it->pos, "Default value type and type declaration differ"); - args.add(type.type_val); - } - lambda_type = type_lambda(node, ret_type, args); - { - sym_type(node, lambda_type); - if(lambda_to_resolve){ - lambda_to_resolve->type = lambda_type; - lambda_to_resolve->state = SYM_RESOLVED; - } - } - - - Operand result = operand_type(lambda_type); - // @todo: We also need to make sure there is a return value when ret type is not void - // @note: then try resolving the block of lambda - if(node->block){ - S64 scope_index = scope_open(); - For(node->args){ - S64 i = node->args.get_index(&it); - Ast_Resolved_Type *type = args[i]; - sym_insert(SYM_VAR, it->name, type, {}, it); - } - For(node->block->stmts){ - resolve_stmt(it, ret_type); - } - scope_close(scope_index); - result.type = lambda_type; - } - - return result; + return resolve_lambda(node); BREAK(); } @@ -544,22 +527,53 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } } - return result; BREAK(); } + invalid_default_case; + } + + return {}; +} + +function Operand +resolve_const(Ast_Expr *ast, Sym *sym){ + switch(ast->kind){ + CASE(LAMBDA, Lambda){ + return resolve_lambda(node, 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_insert(SYM_CONST, it->name, op.type, op.value, it); + } + scope_close(scope_index); + return operand_type(type); + BREAK(); + } + CASE(STRUCT, Struct){ Ast_Resolved_Type *type = type_struct(node); return operand_type(type); BREAK(); } - - invalid_default_case; + default: return resolve_expr(ast, 0, sym); } - - return {}; } function Operand @@ -575,7 +589,7 @@ resolve_binding(Ast *ast, Sym *sym){ } CASE(CONST, Const){ - Operand expr = resolve_expr((Ast_Expr *)node->value, 0, sym); + Operand expr = resolve_const((Ast_Expr *)node->value, sym); if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression"); assert(expr.type); return expr;