diff --git a/build.bat b/build.bat index 254ebe3..dc9c09e 100644 --- a/build.bat +++ b/build.bat @@ -1,7 +1,6 @@ @echo off pushd %~dp0 -rem @todo fix msvc -cl main.cpp -I.. user32.lib -rem clang main.cpp -O0 -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib +rem cl main.cpp -I.. user32.lib +clang main.cpp -O0 -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib popd diff --git a/cgenerate.cpp b/cgenerate.cpp index 30d6a3c..e6ec256 100644 --- a/cgenerate.cpp +++ b/cgenerate.cpp @@ -161,6 +161,20 @@ gen_expr(Ast_Expr *ast){ } } +function void +gen_ast(Ast *ast); +function void +gen_block(Ast_Block *block){ + gen("{"); + global_indent++; + For(block->stmts) { + genln(""); + gen_ast(it[0]); + } + global_indent--; + genln("}"); +} + function void gen_ast(Ast *ast){ switch(ast->kind){ @@ -194,6 +208,27 @@ gen_ast(Ast *ast){ Ast_End(); } + Ast_Begin(AST_IF, Ast_If){ + For(node->ifs){ + if(node->ifs.is_first(it)){ + genln("if("); + gen_expr(it[0]->expr); + gen(")"); + gen_block(it[0]->block); + } + else{ + genln("else"); + if(it[0]->expr){ + gen(" if("); + gen_expr(it[0]->expr); + gen(")"); + } + gen_block(it[0]->block); + } + } + Ast_End(); + } + Ast_Begin(AST_CONST, Ast_Decl){ Sym *sym = resolved_get(node); @@ -211,14 +246,7 @@ gen_ast(Ast *ast){ gen(")"); if(lambda->block) { - gen("{"); - global_indent++; - For(lambda->block->stmts) { - genln(""); - gen_ast(it[0]); - } - global_indent--; - genln("}"); + gen_block(lambda->block); } else gen(";"); } diff --git a/lambdas.kl b/lambdas.kl index 73a7a76..f6a7acc 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -1,5 +1,18 @@ +if_stmt :: (cond: int): int + CONSTANT :: 10 + + if cond + CONSTANT + return cond + CONSTANT + else if cond - CONSTANT + return cond - CONSTANT + else + return CONSTANT + + add_10 :: (size: int): int + // @todo: before the generation c pass, each stage should have it's own + // tree transformation phase, where it yanks functions etc. add_20 :: (new_size: int): int return 20 @@ -13,3 +26,4 @@ return_constant :: (): int returning_void :: (insert: int) return + diff --git a/new_ast.cpp b/new_ast.cpp index 812a93b..39deacd 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -89,6 +89,8 @@ enum Ast_Kind{ AST_COMPOUND_ITEM, AST_COMPOUND, + AST_IF, + AST_IF_NODE, AST_RETURN, AST_BLOCK, AST_LAMBDA, @@ -104,8 +106,12 @@ enum Ast_Kind{ struct Ast{ U64 id; - Ast_Kind kind; Token *pos; + + Ast_Kind kind; + bool is_stmt: 1; + bool is_expr: 1; + bool is_decl: 1; }; struct Ast_Resolved_Type; @@ -161,6 +167,15 @@ struct Ast_Return: Ast{ Ast_Expr *expr; }; +struct Ast_If_Node: Ast{ + Ast_Expr *expr ; + Ast_Block *block; +}; + +struct Ast_If: Ast{ + Array ifs; +}; + struct Ast_Lambda_Arg: Ast_Expr{ Intern_String name; Ast_Typespec *typespec; @@ -315,6 +330,21 @@ ast_block(Token *pos, Array stmts){ return result; } +function Ast_If * +ast_if(Token *pos, Array ifs){ + AST_NEW(If, AST_IF, pos); + result->ifs = ifs.tight_copy(pctx->perm); + return result; +} + +function Ast_If_Node * +ast_if_node(Token *pos, Ast_Expr *expr, Ast_Block *block){ + AST_NEW(If_Node, AST_IF_NODE, pos); + result->block = block; + result->expr = expr; + return result; +} + //----------------------------------------------------------------------------- // Typespecs //----------------------------------------------------------------------------- diff --git a/new_lex.cpp b/new_lex.cpp index e15ed1f..1e47466 100644 --- a/new_lex.cpp +++ b/new_lex.cpp @@ -668,12 +668,14 @@ lex_test(){ }; 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++; } } diff --git a/new_parse.cpp b/new_parse.cpp index ba46168..40c400a 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -59,6 +59,17 @@ token_is(Token_Kind kind, S64 lookahead = 0){ return 0; } +function Token * +token_is_keyword(Intern_String keyword, S64 lookahead = 0){ + Token *token = token_get(lookahead); + if(token->kind == TK_Keyword){ + if(keyword.str == token->intern_val.str){ + return token; + } + } + return 0; +} + function Token * token_match(Token_Kind kind){ Token *token = token_get(); @@ -182,10 +193,37 @@ parse_block(){ if(!token_is_scope()) result->expr = parse_expr(); stmts.add(result); } + else if(token_match_keyword(keyword_if)){ + Array if_nodes = {scratch}; + Ast_Expr *expr = parse_expr(); + Ast_Block *block = parse_block(); + Ast_If_Node *if_node = ast_if_node(token, expr, block); + if_nodes.add(if_node); + + while(token_is(SAME_SCOPE) && token_is_keyword(keyword_else, 1)){ + token_next(); + token = token_next(); + if(token_match_keyword(keyword_if)){ + Ast_Expr *expr = parse_expr(); + Ast_Block *block = parse_block(); + Ast_If_Node *if_node = ast_if_node(token, expr, block); + if_nodes.add(if_node); + } + else{ + Ast_Block *block = parse_block(); + Ast_If_Node *if_node = ast_if_node(token, 0, block); + if_nodes.add(if_node); + break; + } + } + Ast_If *result_if = ast_if(token, if_nodes); + stmts.add(result_if); + + } else{ Ast_Decl *result = parse_decl(false); if(result) stmts.add(result); - else parsing_error(token, "Unexpected token while parsing statement"); + 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); diff --git a/new_resolve.cpp b/new_resolve.cpp index 8bc0477..8b7b1ec 100644 --- a/new_resolve.cpp +++ b/new_resolve.cpp @@ -192,7 +192,6 @@ resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){ function void eval_decl(Ast *ast); function void eval_stmt(Ast *ast, Ast_Resolved_Type *ret){ - switch(ast->kind){ Ast_Begin(AST_RETURN, Ast_Return){ // @todo: need to check if all paths return a value Operand op = {}; @@ -213,6 +212,15 @@ eval_stmt(Ast *ast, Ast_Resolved_Type *ret){ Ast_End(); } + Ast_Begin(AST_IF, Ast_If){ + For(node->ifs){ + if(it[0]->expr) eval_expr(it[0]->expr); + For_It(it[0]->block->stmts, jt){ + eval_stmt(jt[0], ret); + } + } + Ast_End(); + } invalid_default_case; } @@ -409,7 +417,7 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){ invalid_default_case; } } - else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported"); + else parsing_error(node->pos, "Arithmetic on type [%s] is not supported", type_names[result.type->kind]); } return result;