From 9b18c106b65df2c4d055abc38d78b7e3c641ce84 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Wed, 1 Jun 2022 12:13:02 +0200 Subject: [PATCH] Basic variable reassignments --- ccodegen.cpp | 32 +++++++++++++++-- main.cpp | 4 +-- new_lex.cpp | 4 ++- new_parse.cpp | 97 ++++++++++++++++++++++++++++++--------------------- order2.kl | 9 +++++ typecheck.cpp | 25 +++++++------ 6 files changed, 116 insertions(+), 55 deletions(-) diff --git a/ccodegen.cpp b/ccodegen.cpp index f2af288..8b4daba 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -108,7 +108,7 @@ gen_expr(Ast_Expr *ast){ else gen("."); gen_expr(node->right); } - else if(node->op == TK_Colon){ // @todo: I think this needs to be a stmt + else if(node->op == TK_ColonAssign){ // @todo: I think this needs to be a stmt Sym *sym = resolved_get(node); Ast_Atom *atom = (Ast_Atom *)node->left; assert(is_atom(atom)); @@ -274,6 +274,12 @@ gen_ast(Ast *ast){ BREAK(); } + CASE(BINARY,Binary){ + gen_expr(node); + gen(";"); + BREAK(); + } + CASE(FOR, For){ gen("for("); if(node->init) gen_expr(node->init); @@ -391,10 +397,16 @@ compile_string(String filecontent, String filename = "default_name"_s){ ctx.init(scratch, &heap); pctx = &ctx; + F64 tokenize_begin = os_time(); lex_restream(&ctx, filecontent, filename); + F64 tokenize_end = os_time(); + + F64 parse_begin = os_time(); Ast_Package *result = parse_file(); sym_insert_builtins(); pctx->resolving_package = result; + F64 parse_end = os_time(); + gen(R"==( //------------------------------- @@ -403,12 +415,28 @@ compile_string(String filecontent, String filename = "default_name"_s){ //------------------------------- )=="); + F64 resolve_begin = os_time(); resolve_package(result); - // eval_decl(result); + F64 resolve_end = os_time(); + + F64 codegen_begin = os_time(); gen_ast(result); + F64 codegen_end = os_time(); + exp_destroy(&heap); + F64 flattening_begin = os_time(); String string_result = string_flatten(scratch, &pctx->gen); + F64 flattening_end = os_time(); + + printf("\n//-------------------------------"); + printf("\n// Tokenization: %f", tokenize_end - tokenize_begin); + printf("\n// Parsing : %f", parse_end - parse_begin); + printf("\n// Resolving : %f", resolve_end - resolve_begin); + printf("\n// Codegen : %f", codegen_end - codegen_begin); + printf("\n// Flattening : %f", flattening_end - flattening_begin); + printf("\n//-------------------------------"); + return string_result; } diff --git a/main.cpp b/main.cpp index 58d8e37..fa554bf 100644 --- a/main.cpp +++ b/main.cpp @@ -32,9 +32,9 @@ For now I don't thing it should be overloadable. ------------------------------------------------------------------------------- @todo -[ ] - Init statements -[ ] - More operators +[ ] - Init statements, different kinds [+=] [-=] etc. [ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression +[ ] - More operators [ ] - 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 diff --git a/new_lex.cpp b/new_lex.cpp index 9a740fb..c015c66 100644 --- a/new_lex.cpp +++ b/new_lex.cpp @@ -132,7 +132,8 @@ struct Lexer{ S64 token_iter; }; -force_inline B32 token_is_assign(Token *token){return token->kind >= TK_FirstAssign && token->kind <= TK_LastAssign;} +force_inline B32 token_is_assign(Token_Kind token){return token >= TK_FirstAssign && token <= TK_LastAssign;} +force_inline B32 token_is_assign(Token *token){return token_is_assign(token->kind);} function U8 lexc(Lex_Stream *s){ @@ -353,6 +354,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ lex_advance(s); } } + else goto indent_loop_break; } break; // @todo: add [;;] operator which adds new scope diff --git a/new_parse.cpp b/new_parse.cpp index e0976f4..92a33f5 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -79,6 +79,17 @@ token_match(Token_Kind kind){ return 0; } +function Token * +token_match(Token_Kind a, Token_Kind b){ + Token *ta = token_get(); + Token *tb = token_get(1); + if(ta->kind == a && tb->kind == b){ + token_next(); token_next(); + return ta; + } + return 0; +} + function Token * token_match_keyword(Intern_String string){ Token *token = token_get(); @@ -145,6 +156,7 @@ parse_init_stmt(Ast_Expr *expr){ result->flags = set_flag(result->flags, AST_STMT); return result; } + return expr; } @@ -264,9 +276,15 @@ parse_block(){ } else{ - Ast_Named *result = parse_named(false); + Ast *result = parse_named(false); + if(!result){ + result = parse_expr(); + result = parse_init_stmt((Ast_Expr *)result); + } + if(result) stmts.add(result); else parsing_error(token, "Unexpected token [%s] while parsing statement", token_kind_string(token->kind).str); + } } while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); @@ -474,58 +492,57 @@ parse_enum(Token *pos){ return result; } +/* +Needs peeking only because I didn't want to duplicate code +for parsing statements and it makes code nicer. +Statements can have named syntax i := +*/ function Ast_Named * parse_named(B32 is_global){ Ast_Named *result = 0; - if(is_global) token_match(SAME_SCOPE); - 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(is_global) { + token_match(SAME_SCOPE); + if(pctx->indent != 0){ + parsing_error(token_get(), "Top level declarations shouldn't be indented"); + } + } - // @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, (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 - else{ - Ast_Expr *expr = parse_expr(); - result = ast_const(name, name->intern_val, expr); - } + Token *name = token_get(); + if(token_match(TK_Identifier, TK_DoubleColon)){ + // @note 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, (Ast_Expr *)struct_val); } - else if(token_match(TK_ColonAssign)){ - Ast_Expr *expr = parse_expr(); - result = ast_var(name, 0, name->intern_val, expr); + 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); } - // @note: parse variable - else if(token_match(TK_Colon)){ - Ast_Expr *typespec = typespec = parse_expr(); - Ast_Expr *expr = parse_assign_expr(); - result = ast_var(name, typespec, name->intern_val, expr); - } + // @note parse constant expression else{ - Token *token = token_get(); - parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str); + Ast_Expr *expr = parse_expr(); + result = ast_const(name, name->intern_val, expr); } } - else if(!token_is(TK_End)){ - if(is_global){ - Token *token = token_get(); - parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str); - } + else if(token_match(TK_Identifier, TK_Colon)){ + Ast_Expr *typespec = typespec = parse_expr(); + Ast_Expr *expr = parse_assign_expr(); + result = ast_var(name, typespec, name->intern_val, expr); } + + else if(token_match(TK_Identifier, TK_ColonAssign)){ + Ast_Expr *expr = parse_expr(); + result = ast_var(name, 0, name->intern_val, expr); + } + else if(is_global && name->kind != TK_End){ + parsing_error(name, "Unexpected token: [%s] when parsing a declaration", token_kind_string(name->kind).str); + } + return result; } + diff --git a/order2.kl b/order2.kl index 6bb3efb..86c28b5 100644 --- a/order2.kl +++ b/order2.kl @@ -43,6 +43,15 @@ pointer := &with_type deref := *pointer +test_stmts :: () + i := 0 + i += 4 + i -= 1 + i *= 2 + i /= 2 + i %= 2 + + /* for pass diff --git a/typecheck.cpp b/typecheck.cpp index aee5add..1471191 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -64,17 +64,22 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ } CASE(BINARY, Binary){ - switch(node->op){ - 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); - Ast_Atom *atom = (Ast_Atom *)node->left; // @todo use left operand - Sym *sym = sym_new_resolved(SYM_VAR, atom->intern_val, right.type, right.value, node); - sym_insert(sym); - }break; - invalid_default_case; + if(node->op == TK_ColonAssign){ + // Operand left = resolve_expr(node->left); // needs to be lvalue + Operand right = resolve_expr(node->right); + assert(node->left->kind == AST_IDENT); + Ast_Atom *atom = (Ast_Atom *)node->left; // @todo use left operand + Sym *sym = sym_new_resolved(SYM_VAR, atom->intern_val, right.type, right.value, node); + sym_insert(sym); } + else if(token_is_assign(node->op)){ + // @todo: assign value to constant + // @todo: lvalue concept, passing down syms to change (constants) + Operand left = resolve_expr(node->left); + Operand right = resolve_expr(node->right); + if(left.type != right.type) parsing_error(node->pos, "Different types"); + } + else invalid_codepath; BREAK(); }