From 5176b40204e12bfe7c68c225dd4fb3df33c7c33f Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 24 May 2022 20:33:11 +0200 Subject: [PATCH] Generating valid c code, more work on null values --- build.bat | 4 +- cgenerate.cpp | 232 ++++++++++++++++++++++++++++++++++++++ generate.c | 66 ----------- ideas.cpp | 33 ------ lex.c | 84 +++++++------- main.cpp | 7 +- new_ast.cpp | 50 ++++---- new_lex.cpp | 152 +++++++++++++------------ new_parse.cpp | 99 ++++++++-------- new_resolve.cpp | 215 +++++++++++++++++++++-------------- new_type.cpp | 142 +++++++++++------------ output.cc | 294 ------------------------------------------------ parse.c | 74 ++++++------ test.cc | 286 ---------------------------------------------- test2.cc | 31 ----- test3.kl | 30 +++-- type.c | 157 -------------------------- 17 files changed, 698 insertions(+), 1258 deletions(-) create mode 100644 cgenerate.cpp delete mode 100644 generate.c delete mode 100644 ideas.cpp delete mode 100644 output.cc delete mode 100644 test.cc delete mode 100644 test2.cc delete mode 100644 type.c diff --git a/build.bat b/build.bat index 8ae8a3b..6c53d87 100644 --- a/build.bat +++ b/build.bat @@ -1,3 +1,5 @@ @echo off -clang main.cpp -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib +pushd %~dp0 +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 new file mode 100644 index 0000000..86a3b4a --- /dev/null +++ b/cgenerate.cpp @@ -0,0 +1,232 @@ + +#define genln(...) do{printf("\n"); gen_indent(); gen(__VA_ARGS__); }while(0) +#define gen(...) printf(__VA_ARGS__) +global S32 global_indent; + +function void +gen_indent(){ + for(S32 i = 0; i < global_indent; i++) gen(" "); +} + +// @todo: Gen complicated decl +//array 10 ( pointer (pointer array 5 int a)) +// int (*(*(a[5])))[10] +// +// 1 Get to the bottom +// 2 Add variable name +// 3 Going backwards add arrays and pointers in parens +// 4 Add type name on the left side + +function void +gen_simple_decl_prefix(Ast_Resolved_Type *ast){ + switch(ast->kind){ + case TYPE_Int: gen("int "); break; + case TYPE_Bool: gen("bool "); break; + case TYPE_Unsigned: gen("unsigned "); break; + case TYPE_String: gen("String "); break; + case TYPE_Void: gen("void "); break; + 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; + invalid_default_case; + } +} + +function void +gen_simple_decl_postfix(Ast_Resolved_Type *ast){ + switch(ast->kind){ + case TYPE_Int: break; + case TYPE_Bool: break; + case TYPE_Unsigned: break; + case TYPE_String: break; + case TYPE_Void: break; + 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; + invalid_default_case; + } +} + +function void +gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){ + if(ast->kind == TYPE_Lambda) { + gen_simple_decl_prefix(ast->func.ret); + gen("(*%s)(", name.str); + For(ast->func.args){ + gen_simple_decl_prefix(it[0]); + if(it != ast->func.args.end() - 1) gen(", "); + } + gen(")"); + } + else{ + gen_simple_decl_prefix(ast); + if(name.len) { + gen("%s", name.str); + gen_simple_decl_postfix(ast); + } + } +} + +function void +gen_expr(Ast_Expr *ast){ + switch(ast->kind){ + Ast_Begin(AST_IDENT, Ast_Expr){ + gen("%s", node->intern_val.str); + Ast_End(); + } + + Ast_Begin(AST_INT, Ast_Expr){ + gen("%lld", node->int_val); + Ast_End(); + } + + Ast_Begin(AST_STR, Ast_Expr){ + gen("LIT(\"%s\")", node->intern_val.str); + Ast_End(); + } + + Ast_Begin(AST_INDEX, Ast_Expr){ + gen_expr(node->index.expr); + gen("["); + gen_expr(node->index.index); + gen("]"); + Ast_End(); + } + + Ast_Begin(AST_UNARY, Ast_Expr){ + switch(node->unary.op){ + case TK_Pointer: { + gen("(*"); + gen_expr(node->unary.expr); + gen(")"); + } break; + case TK_Dereference: { + gen("(&"); + gen_expr(node->unary.expr); + gen(")"); + } break; + invalid_default_case; + } + Ast_End(); + } + + Ast_Begin(AST_CAST, Ast_Expr){ + gen("("); + gen("("); + gen_simple_decl(node->cast.typespec->resolved_type, {}); + gen(")"); + gen_expr(node->cast.expr); + gen(")"); + Ast_End(); + } + + Ast_Begin(AST_COMPOUND, Ast_Expr){ + gen("("); + gen_simple_decl(node->compound.type, {}); + gen(")"); + + gen("{"); + For(node->compound.exprs){ + auto comp = it[0]->compound_item; + if(comp.name){ + gen("["); + gen_expr(comp.name); + gen("] = "); + } + if(comp.index){ + gen("["); + gen_expr(comp.index); + gen("] = "); + } + assert(comp.item); + gen_expr(comp.item); + + if(!node->compound.exprs.is_last(it)) gen(", "); + } + gen("}"); + + Ast_End(); + } + + invalid_default_case; + } +} + +function void +gen_ast(Ast *ast){ + switch(ast->kind){ + + Ast_Begin(AST_PACKAGE, Ast_Package){ + For(node->decls) gen_ast(*it); + Ast_End(); + } + + Ast_Begin(AST_VAR, Ast_Decl){ + genln(""); + Sym *sym = sym_get(node->name); + gen_simple_decl(sym->type, node->name); + if(node->var.expr){ + gen(" = "); + gen_expr(node->var.expr); + } + gen(";"); + Ast_End(); + } + + Ast_Begin(AST_CONST, Ast_Decl){ + Sym *sym = sym_get(node->name); + + if(sym->type->kind == TYPE_Lambda){ + if(node->var.expr->kind == AST_LAMBDA){ + Ast_Lambda *lambda = (Ast_Lambda *)node->var.expr; + genln(""); + gen_simple_decl(lambda->ret->resolved_type, node->name); + gen("("); + For(lambda->params){ + assert(it[0]->kind == AST_LAMBDA_PARAM); + gen_simple_decl(it[0]->lambda_param.typespec->resolved_type, it[0]->lambda_param.name); + if(it != (lambda->params.end() - 1)) gen(", "); + } + gen(")"); + } + else{ + genln(""); + gen_simple_decl(sym->type, node->name); + gen(" = "); + gen_expr(node->var.expr); + gen(";"); + } + } + else if(sym->type == type_int){ + genln("enum { %s = %lld };", node->name.str, sym->int_val); + } + else if(sym->type == type_string){ + genln("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str); + } + else{ + parsing_error(node->pos, "Unhandled type of constant expression"); + } + + Ast_End(); + } + + invalid_default_case; + } +} + +function void +test_gen(){ + TEST_PARSER(); + String filename = "test3.kl"_s; + String file_content = os_read_file(scratch, filename); + lex_restream(&ctx, file_content, filename); + Ast_Package *result = parse_file(); + sym_insert_builtins(); + eval_decl(result); + gen(R"==( +#define null_pointer 0 +#define null_lambda 0 + )=="); + gen_ast(result); + __debugbreak(); +} diff --git a/generate.c b/generate.c deleted file mode 100644 index 330fbb3..0000000 --- a/generate.c +++ /dev/null @@ -1,66 +0,0 @@ -#define _CRT_SECURE_NO_WARNINGS -#include -#include - -#include "lang.h" -#include "os.h" -#include "memory.h" - -#include "common.c" -#include "memory.c" -#include "scratch.c" -#include "os_win32.c" - -#include "new_lex.c" - -//----------------------------------------------------------------------------- -// String replacing util -//----------------------------------------------------------------------------- -typedef struct String_Map String_Map; -struct String_Map{ - String replace; - String with; -}; - -function void -output_template(FILE *f, String filename, String_Map *map, SizeU map_cap){ - Arena *scratch = arena_begin_scratch(); - String file = os_read_file(scratch, filename); - Token_Array array = lex_stream(scratch, file, filename); - for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){ - String string = t->string; - for(SizeU i = 0; i < map_cap; i++){ - if(string_compare(string, map[i].replace)){ - string = map[i].with; - break; - } - } - - - fprintf(f, "%.*s", (int)string.len, string.str); - if(t->kind == TK_OpenBrace) fprintf(f, "\n"); - if(t->kind == TK_CloseBrace && token_array_iter_peek(&array, 0)->kind != TK_Semicolon) fprintf(f, "\n"); - if(t->kind == TK_Semicolon) fprintf(f, "\n"); - if(t->kind == TK_Keyword) fprintf(f, " "); - if(t[0].kind == TK_Identifier && token_array_iter_peek(&array, 0)->kind == TK_Identifier) fprintf(f, " "); - token_array_iter_peek(&array, 1); - } - arena_end_scratch(); -} - -int main(){ - - FILE *f = fopen("generated.c", "w"); - assert(f); - String_Map map[] = { - {lit("Type"), lit("Decl")}, - {lit("first"), lit("list_decl.first")}, - {lit("last"), lit("list_decl.last")}, - {lit("remove"), lit("decl_list_remove")}, - {lit("push_front"), lit("decl_dll_list_push_front")}, - {lit("push"), lit("decl_dll_list_push")}, - }; - output_template(f, lit("dllqueue.c"), map, buff_cap(map)); - - fclose(f); -} \ No newline at end of file diff --git a/ideas.cpp b/ideas.cpp deleted file mode 100644 index 919990b..0000000 --- a/ideas.cpp +++ /dev/null @@ -1,33 +0,0 @@ -New_Data_Type::typedef int; -CONST_VAL::const 324; - -Ideas::enum{ - One, - Two, - Three -} - -Data::struct{ - first: int; - second: int; - idea: Ideas; -} - - -function_call::(first_param: Data*, second_param: int[32]){ - first_param.first = 10; - first_param.second = 10; - first_param.idea = Ideas.One; - p:= first_param; - - for i in 0...32 { - second_param[i] = i; - } - - for i := 0; i < 32; i++ { - second_param[i] = i; - } - - return p; -} - diff --git a/lex.c b/lex.c index 9562807..225c2c7 100644 --- a/lex.c +++ b/lex.c @@ -27,7 +27,7 @@ function void init_default_keywords(Intern_Table *t){ keyword_if = intern_string(t, lit("if")); first_keyword = keyword_if.s.str; - + keyword_cast = intern_string(t, lit("cast")); keyword_for = intern_string(t, lit("for")); keyword_else = intern_string(t, lit("else")); @@ -44,16 +44,16 @@ init_default_keywords(Intern_Table *t){ keyword_case = intern_string(t, lit("case")); keyword_struct = intern_string(t, lit("struct")); keyword_enum = intern_string(t, lit("enum")); - + keyword_union = intern_string(t, lit("union")); last_keyword = keyword_union.s.str; - + intern_char = intern_string(t, lit("char")); intern_void = intern_string(t, lit("void")); intern_int = intern_string(t, lit("int")); } -function B32 +function B32 lex_is_keyword(Intern_String str){ B32 result = str.s.str >= first_keyword && str.s.str <= last_keyword; return result; @@ -61,7 +61,7 @@ lex_is_keyword(Intern_String str){ typedef enum Token_Kind{ TK_End, - + TK_Mul, TK_Div, TK_Mod, @@ -69,12 +69,12 @@ typedef enum Token_Kind{ TK_RightShift, TK_FirstMul = TK_Mul, TK_LastMul = TK_RightShift, - + TK_Add, TK_Sub, TK_FirstAdd = TK_Add, TK_LastAdd = TK_Sub, - + TK_Equals, TK_LesserThenOrEqual, TK_GreaterThenOrEqual, @@ -83,15 +83,15 @@ typedef enum Token_Kind{ TK_NotEquals, TK_FirstCompare = TK_Equals, TK_LastCompare = TK_NotEquals, - + TK_BitAnd, TK_BitOr, - TK_BitXor, + TK_Pointer, TK_And, TK_Or, TK_FirstLogical = TK_BitAnd, TK_LastLogical = TK_Or, - + TK_Neg, TK_Not, TK_OpenParen, @@ -106,9 +106,9 @@ typedef enum Token_Kind{ TK_ThreeDots, TK_Semicolon, TK_Dot, - + TK_Colon, - + TK_Assign, TK_ColonAssign, TK_DivAssign, @@ -123,14 +123,14 @@ typedef enum Token_Kind{ TK_RightShiftAssign, TK_FirstAssign = TK_Assign, TK_LastAssign = TK_RightShiftAssign, - + TK_DoubleColon, TK_At, TK_Decrement, TK_Increment, TK_PostDecrement, TK_PostIncrement, - + TK_Arrow, TK_ExprSizeof, TK_DocComment, @@ -150,14 +150,14 @@ typedef struct Token{ String string; struct{U8 *str; S64 len;}; }; - + union { U64 int_val; F64 float_val; String error_val; Intern_String intern_val; }; - + String file; S32 line; U8 *line_begin; @@ -167,7 +167,7 @@ typedef struct Token{ typedef struct Lex_Stream{ String stream; S64 iter; - + U8 *line_begin; String file; S32 line; @@ -207,7 +207,7 @@ lex_is_numeric(U8 c){ return result; } -function B32 +function B32 lex_is_alphanumeric(U8 c){ B32 result = lex_is_numeric(c) || lex_is_alphabetic(c); return result; @@ -226,7 +226,7 @@ token_error(Token *t, String error_val){ } function void -lex_parse_u64(Token *t){ +lex_parse_u64(Token *t){ U64 result = 0; U64 m = 1; for(S64 i = t->len - 1; i >= 0; --i){ @@ -257,7 +257,7 @@ lex_advance(Lex_Stream *s){ } } -function void +function void lex_parse_string(Lex_Stream *s, Token *t, U8 c){ for(;;){ if(lexc(s) == '\\') lex_advance(s); @@ -301,14 +301,14 @@ lex__stream(Token_Array *array, Lex_Stream *s){ while(lexc(s)){ while(lex_is_whitespace(lexc(s))) lex_advance(s); - + Token t = {0}; t.str = lexcp(s); t.file = s->file; t.line = s->line; t.line_begin = s->line_begin; lex_advance(s); - + switch(*t.str){ case 0: break; case '@': t.kind = TK_At; break; @@ -324,7 +324,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ case ';': t.kind = TK_Semicolon; break; case '#': t.kind = TK_Pound; break; CASE2('!', TK_Not, TK_NotEquals); - CASE2('^', TK_BitXor, TK_XorAssign); + CASE2('^', TK_Pointer, TK_XorAssign); CASE2('=', TK_Assign, TK_Equals); CASE2('*', TK_Mul, TK_MulAssign); CASE2('%', TK_Mod, TK_ModAssign); @@ -342,8 +342,8 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_Dot; } } break; - - + + case '<': { if (lexc(s) == '<') { lex_advance(s); @@ -363,7 +363,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_LesserThen; } } break; - + case '>': { if (lexc(s) == '>') { lex_advance(s); @@ -383,7 +383,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_GreaterThen; } } break; - + case ':': { if (lexc(s) == ':') { lex_advance(s); @@ -397,7 +397,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_Colon; } } break; - + case '-':{ if (lexc(s) == '=') { lex_advance(s); @@ -415,11 +415,11 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_Sub; } } break; - - + + case '\'':{not_implemented;} break; case '"': { - t.kind = TK_StringLit; + t.kind = TK_StringLit; lex_parse_string(s,&t,'"'); if(t.kind != TK_Error){ t.str += 1; @@ -427,7 +427,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ } t.intern_val = intern_string(&array->interns, t.string); } break; - + case '/': { if(lexc(s) == '='){ t.kind = TK_DivAssign; @@ -464,7 +464,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_Div; } } break; - + case '0':case '1':case '2':case '3':case '4': case '5':case '6':case '7':case '8':case '9':{ t.kind = TK_Integer; @@ -473,7 +473,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){ lex_set_len(s, &t); lex_parse_u64(&t); } break; - + case 'A':case 'a':case 'M':case 'm':case 'B': case 'b':case 'N':case 'n':case 'C':case 'c':case 'O': case 'o':case 'D':case 'd':case 'P':case 'p':case 'E': @@ -492,15 +492,15 @@ lex__stream(Token_Array *array, Lex_Stream *s){ t.kind = TK_Keyword; } } break; - + default: { token_error(&t, lit("Unknown token")); } } - + if(t.len==0) lex_set_len(s,&t); - + token_array_push(array, &t); } } @@ -538,13 +538,13 @@ lex_test(){ "\"Test_Meme\"+=-===42524 4294967295 18446744073709551615" "for if while switch :="); Token_Array array = lex_stream(scratch, test, lit("Test1")); - + Token_Kind kind[] = { TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen, TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon, 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_Equals, TK_Integer, TK_Integer, TK_Integer, TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, TK_ColonAssign, TK_End }; String strs[] = { @@ -558,7 +558,7 @@ lex_test(){ U64 vals[] = { 42524, 4294967295, 18446744073709551615llu }; - + int i = 0; int ui = 0; for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){ @@ -569,7 +569,7 @@ lex_test(){ } } arena_end_scratch(); - + } //----------------------------------------------------------------------------- @@ -584,7 +584,7 @@ global const char *token_kind_string[] = { [TK_Mod] = "%", [TK_BitAnd] = "&", [TK_BitOr] = "|", - [TK_BitXor] = "^", + [TK_Pointer] = "^", [TK_Neg] = "~", [TK_Not] = "!", [TK_OpenParen] = "(", diff --git a/main.cpp b/main.cpp index 76045b6..c4426f6 100644 --- a/main.cpp +++ b/main.cpp @@ -5,21 +5,20 @@ #include "new_parse.cpp" #include "new_type.cpp" #include "new_resolve.cpp" +#include "cgenerate.cpp" int main(){ test_os_memory(); thread_ctx_init(); - + test_gen(); test_unicode(); test_resolve(); test_types(); test_parse_expr(); - + map_test(); test_array(); test_string_builder(); test_intern_table(); lex_test(); } - - diff --git a/new_ast.cpp b/new_ast.cpp index 7374847..aec6cac 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -4,7 +4,7 @@ // // Parser::ast_arena - arena for asts // Lexer::interns::string_allocator - arena for interns -// +// Intern_String keyword_struct; Intern_String keyword_union; Intern_String keyword_cast; @@ -19,21 +19,25 @@ const U64 Parse_Ctx_ID = 115151; struct Parse_Ctx:Lexer{ Allocator *perm; // Stores: AST, tokens, interns Allocator *heap; - + U64 unique_ids; Map global_syms; Map type_map; - + Token empty_token; S64 indent; - + + Intern_String intern(String string){ + return intern_string(&interns, string); + } + void init(Allocator *perm_allocator, Allocator *heap_allocator){ perm = perm_allocator; heap = heap_allocator; - + global_syms = {heap}; type_map = {heap}; - + lex_init(perm, heap, this); keyword_struct= intern_string(&interns, "struct"_s); keyword_union = intern_string(&interns, "union"_s); @@ -41,7 +45,7 @@ struct Parse_Ctx:Lexer{ keyword_enum = intern_string(&interns, "enum"_s); interns.first_keyword = keyword_struct.str; interns.last_keyword = keyword_enum.str; - + intern_void = intern_string(&interns, "void"_s); intern_int = intern_string(&interns, "int"_s); intern_str = intern_string(&interns, "String"_s); @@ -55,9 +59,9 @@ thread_local Parse_Ctx *pctx; //----------------------------------------------------------------------------- enum Ast_Kind{ AST_NONE, - + AST_PACKAGE, - + AST_STR, AST_INT, AST_CAST, @@ -67,12 +71,12 @@ enum Ast_Kind{ AST_BINARY, AST_COMPOUND_ITEM, AST_COMPOUND, - + AST_LAMBDA, AST_LAMBDA_PARAM, AST_CONST, AST_VAR, - + AST_TYPESPEC_IDENT, AST_TYPESPEC_POINTER, AST_TYPESPEC_ARRAY, @@ -85,6 +89,7 @@ struct Ast{ Token *pos; }; +struct Ast_Resolved_Type; struct Ast_Typespec; struct Ast_Expr:Ast{ union{ @@ -94,13 +99,13 @@ struct Ast_Expr:Ast{ Token_Kind op; Ast_Expr *expr; }unary; - struct{ Token_Kind op; Ast_Expr *left; Ast_Expr *right; } binary; struct{ + Ast_Resolved_Type *type; Ast_Typespec *typespec; Array exprs; }compound; @@ -124,12 +129,19 @@ struct Ast_Expr:Ast{ }; }; +struct Ast_Block : Ast { + Array stmts; +}; + struct Ast_Lambda : Ast_Expr { Array params; Ast_Typespec *ret; + Ast_Block *block; }; +struct Ast_Resolved_Type; struct Ast_Typespec:Ast{ + Ast_Resolved_Type *resolved_type; union{ Ast_Typespec *base; Intern_String name; @@ -148,10 +160,6 @@ struct Ast_Decl:Ast{ Ast_Typespec *typespec; Ast_Expr *expr; }var; - struct{ - Array args; - Ast_Typespec *ret; - }func; }; }; @@ -164,10 +172,10 @@ struct Ast_Package:Ast{ // AST Constructors beginning with expressions //----------------------------------------------------------------------------- #define AST_NEW(T,ikind,ipos) \ -Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \ -result->kind = ikind; \ -result->pos = ipos; \ -result->id = ++pctx->unique_ids + Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \ + result->kind = ikind; \ + result->pos = ipos; \ + result->id = ++pctx->unique_ids function Ast_Expr * ast_expr_string(Token *pos, Intern_String string){ @@ -327,4 +335,4 @@ ast_package(Token *pos, String name, Array decls){ result->decls = decls.tight_copy(pctx->perm); result->name = intern_string(&pctx->interns, name); return result; -} \ No newline at end of file +} diff --git a/new_lex.cpp b/new_lex.cpp index 2b7337b..d092b46 100644 --- a/new_lex.cpp +++ b/new_lex.cpp @@ -1,7 +1,7 @@ enum Token_Kind{ TK_End, - + TK_Mul, TK_Div, TK_Mod, @@ -9,12 +9,12 @@ enum Token_Kind{ TK_RightShift, TK_FirstMul = TK_Mul, TK_LastMul = TK_RightShift, - + TK_Add, TK_Sub, TK_FirstAdd = TK_Add, TK_LastAdd = TK_Sub, - + TK_Equals, TK_LesserThenOrEqual, TK_GreaterThenOrEqual, @@ -23,15 +23,14 @@ enum Token_Kind{ TK_NotEquals, TK_FirstCompare = TK_Equals, TK_LastCompare = TK_NotEquals, - + TK_BitAnd, TK_BitOr, - TK_BitXor, TK_And, TK_Or, TK_FirstLogical = TK_BitAnd, TK_LastLogical = TK_Or, - + TK_Neg, TK_Not, TK_OpenParen, @@ -46,10 +45,10 @@ enum Token_Kind{ TK_ThreeDots, TK_Semicolon, TK_Dot, - + TK_NewLine, TK_Colon, - + TK_Assign, TK_DivAssign, TK_MulAssign, @@ -63,14 +62,14 @@ enum Token_Kind{ TK_RightShiftAssign, TK_FirstAssign = TK_Assign, TK_LastAssign = TK_RightShiftAssign, - + TK_DoubleColon, TK_At, TK_Decrement, TK_Increment, TK_PostDecrement, TK_PostIncrement, - + TK_Arrow, TK_ExprSizeof, TK_DocComment, @@ -82,8 +81,8 @@ enum Token_Kind{ TK_Float, TK_Integer, TK_Keyword, - - TK_Pointer = TK_BitXor, + + TK_Pointer, TK_Dereference, }; @@ -93,7 +92,7 @@ struct Token{ String string; struct{U8 *str; S64 len;}; }; - + union { U64 int_val; F64 float_val; @@ -101,7 +100,7 @@ struct Token{ Intern_String intern_val; S64 indent; }; - + String file; S32 line; U8 *line_begin; @@ -110,7 +109,7 @@ struct Token{ struct Lex_Stream{ String stream; S64 iter; - + U8 *line_begin; String file; S32 line; @@ -157,7 +156,7 @@ lex_is_numeric(U8 c){ return result; } -function B32 +function B32 lex_is_alphanumeric(U8 c){ B32 result = lex_is_numeric(c) || lex_is_alphabetic(c); return result; @@ -172,9 +171,9 @@ lex_set_len(Lex_Stream *s, Token *token){ function void lex_set_keywords(Lexer *lexer, Array keywords){ Intern_String keyword = {}; - Iter(keywords){ + For(keywords){ keyword = intern_string(&lexer->interns, *it); - if(it == keywords.begin()) + if(it == keywords.begin()) lexer->interns.first_keyword = keyword.str; } lexer->interns.last_keyword = keyword.str; @@ -193,7 +192,7 @@ token_error(Token *t, String error_val){ } function void -lex_parse_u64(Token *t){ +lex_parse_u64(Token *t){ U64 result = 0; U64 m = 1; for(S64 i = t->len - 1; i >= 0; --i){ @@ -224,7 +223,7 @@ lex_advance(Lex_Stream *s){ } } -function void +function void lex_parse_string(Lex_Stream *s, Token *t, U8 c){ for(;;){ if(lexc(s) == '\\') lex_advance(s); @@ -241,39 +240,39 @@ lex_parse_string(Lex_Stream *s, Token *t, U8 c){ } } -#define CASE2(op, OpName, Assign) \ -case op: \ -if (lexc(s) == '=') { \ -lex_advance(s); \ -t.kind = Assign; \ -} else { \ -t.kind = OpName; \ -} \ -break -#define CASE3(op, OpName, Assign, Incr) \ -case op: \ -if (lexc(s) == '=') { \ -lex_advance(s); \ -t.kind = Assign; \ -} else if (lexc(s) == op) { \ -lex_advance(s); \ -t.kind = Incr; \ -} else { \ -t.kind = OpName; \ -} \ -break +#define CASE2(op, OpName, Assign) \ + case op: \ + if (lexc(s) == '=') { \ + lex_advance(s); \ + t.kind = Assign; \ + } else { \ + t.kind = OpName; \ + } \ + break +#define CASE3(op, OpName, Assign, Incr) \ + case op: \ + if (lexc(s) == '=') { \ + lex_advance(s); \ + t.kind = Assign; \ + } else if (lexc(s) == op) { \ + lex_advance(s); \ + t.kind = Incr; \ + } else { \ + t.kind = OpName; \ + } \ + break function void lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ while(lexc(s)){ - + Token t = {}; t.str = lexcp(s); t.file = s->file; t.line = s->line; t.line_begin = s->line_begin; lex_advance(s); - + switch(*t.str){ case 0 : break; case '@': t.kind = TK_At; break; @@ -287,8 +286,8 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ case '~': t.kind = TK_Neg; break; case '?': t.kind = TK_Question; break; case '#': t.kind = TK_Pound; break; + case '^': t.kind = TK_Pointer; break; CASE2('!', TK_Not, TK_NotEquals); - CASE2('^', TK_BitXor, TK_XorAssign); CASE2('=', TK_Assign, TK_Equals); CASE2('*', TK_Mul, TK_MulAssign); CASE2('%', TK_Mod, TK_ModAssign); @@ -298,15 +297,15 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ #undef CASE2 #undef CASE3 case ';': { - t.kind = TK_Semicolon; + t.kind = TK_Semicolon; }break; - + case ' ' : s->stream.str -= 1; case '\n': { t.kind = TK_NewLine; - if(lexc(s) == '\r') + if(lexc(s) == '\r') lex_advance(s); - + for(;;){ if(lexc(s) == ' ') { t.indent++; @@ -316,7 +315,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ else break; lex_advance(s); } - + }break; case '.': { if(lexc(s) == '.' && lexci(s,1) == '.') { @@ -327,8 +326,8 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_Dot; } } break; - - + + case '<': { if (lexc(s) == '<') { lex_advance(s); @@ -348,7 +347,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_LesserThen; } } break; - + case '>': { if (lexc(s) == '>') { lex_advance(s); @@ -368,7 +367,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_GreaterThen; } } break; - + case ':': { if (lexc(s) == ':') { lex_advance(s); @@ -378,7 +377,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_Colon; } } break; - + case '-':{ if (lexc(s) == '=') { lex_advance(s); @@ -396,11 +395,11 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_Sub; } } break; - - + + case '\'':{not_implemented;} break; case '"': { - t.kind = TK_StringLit; + t.kind = TK_StringLit; lex_parse_string(s,&t,'"'); if(t.kind != TK_Error){ t.str += 1; @@ -408,7 +407,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ } t.intern_val = intern_string(table, t.string); } break; - + case '/': { if(lexc(s) == '='){ t.kind = TK_DivAssign; @@ -445,7 +444,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_Div; } } break; - + case '0':case '1':case '2':case '3':case '4': case '5':case '6':case '7':case '8':case '9':{ t.kind = TK_Integer; @@ -454,7 +453,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ lex_set_len(s, &t); lex_parse_u64(&t); } break; - + case 'A':case 'a':case 'M':case 'm':case 'B': case 'b':case 'N':case 'n':case 'C':case 'c':case 'O': case 'o':case 'D':case 'd':case 'P':case 'p':case 'E': @@ -473,23 +472,23 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ t.kind = TK_Keyword; } } break; - + default: { token_error(&t, "Unknown token"_s); } } - + if(t.len==0) lex_set_len(s,&t); - + B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0; if(!skip){ array->add(t); } - + while(lex_is_whitespace(lexc(s))) lex_advance(s); - + if(s->iter >= s->stream.len) // End of stream break; } @@ -510,7 +509,12 @@ lex_make(Allocator *token_string_arena, Allocator *map_allocator){ function void lex_restream(Lexer *lexer, String istream, String file){ - lexer->stream = {istream, 0, istream.str, file, 0}; + lexer->stream = {}; + lexer->stream.stream = istream; + lexer->stream.line_begin = istream.str; + lexer->stream.file = file; + + lexer->tokens.clear(); lexer->token_iter = 0; lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream); @@ -529,26 +533,26 @@ lex_test(){ String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"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[] = { TK_Keyword, TK_NewLine, TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen, TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon, 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_Equals, TK_Integer, TK_Integer, TK_Integer, + TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, TK_Colon, TK_Assign, TK_End }; String strs[] = { @@ -562,7 +566,7 @@ lex_test(){ U64 vals[] = { 42524, 4294967295, 18446744073709551615llu }; - + int ui = 0; For(arr){ assert(it->kind == kind[i]); @@ -576,7 +580,7 @@ lex_test(){ //----------------------------------------------------------------------------- // Token metadata //----------------------------------------------------------------------------- -function String +function String token_kind_string(Token_Kind kind){ switch(kind){ case TK_End: return "End of stream"_s; @@ -587,7 +591,7 @@ token_kind_string(Token_Kind kind){ case TK_Mod: return "%"_s; case TK_BitAnd: return "&"_s; case TK_BitOr: return "|"_s; - case TK_BitXor: return "^"_s; + case TK_Pointer: return "^"_s; case TK_Neg: return "~"_s; case TK_Not: return "!"_s; case TK_OpenParen: return "("_s; diff --git a/new_parse.cpp b/new_parse.cpp index 335853a..13152de 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -9,12 +9,12 @@ token_get(S64 i = 0){ if(result->kind == TK_NewLine){ pctx->indent = result->indent; } - + return result; } function Token * -token_next(){ +token_next(){ Token *token = token_get(); pctx->token_iter++; return token; @@ -51,28 +51,28 @@ token_match_keyword(Intern_String string){ } function void -parsing_error(Token *token, const char *str, ...){ +parsing_error(Token *token, const char *str, ...){ Scratch scratch; STRING_FMT(scratch, str, string); - + // @Note(Krzosa): Print nice error message printf("\nError: %s", string.str); if(token){ printf(" %s:%d\n", token->file.str, (S32)token->line); - + // @Note(Krzosa): Print error line { int i = 0; while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; printf("%.*s\n", i, token->line_begin); - + // @Note(Krzosa): Print error marker int token_i = token->str - token->line_begin; for(int i = 0; i < token_i-2; i++) printf(" "); printf("^^^^^^\n"); } } - + __debugbreak(); } @@ -97,15 +97,15 @@ compare = == | != | >= | > | <= | < logical = [&|^] | && | || unary = [&*-!~+] | ++ | -- -atom_expr = Int -| Float -| String +atom_expr = Int +| Float +| String | Identifier | 'cast' '(' typespec ',' expr ')' | 'size_type' '(' typespec ')' | 'size_expr' '(' expr ')' | '{' compound_expr '}' -| '(' expr ')' +| '(' expr ')' | '(' ':' typespec ')' '{' compound_expr '}' postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* unary_expr = unary ? unary_expr : atom_expr @@ -143,17 +143,17 @@ parse_expr_compound(){ name = ast_expr_identifier(token, token->intern_val); token_expect(TK_Assign); } - + Ast_Expr *item = parse_expr(); Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item); exprs.add(item_comp); - + if(!token_match(TK_Comma)){ break; } } token_expect(TK_CloseBrace); - + Ast_Expr *result = ast_expr_compound(pos, 0, exprs); return result; } @@ -165,14 +165,24 @@ parse_optional_type(){ return result; } +/* +function Ast_Block * +parse_block(){ + Ast_Block *result = 0; + if(token_match(TK_NewScope)){ + + } + return result; +} + */ + function Ast_Lambda * parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently - // @Todo(Krzosa): Combine this with typespec function parsing Scratch scratch; Array params = {scratch}; - // @Note(Krzosa): No need to guard against "()" + // @Note(Krzosa): No need to guard against "()" // We needed to lookahead to verify it's a function - // and this routine only fires when we have situation + // and this routine only fires when we have situation // with at least one parameter for(;;){ Token *name = token_expect(TK_Identifier); @@ -180,12 +190,14 @@ parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typesp Ast_Typespec *typespec = parse_typespec(); Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec); params.add(param); - + if(!token_match(TK_Comma)){ break; } } token_expect(TK_CloseParen); + + //Ast_Block *block = parse_block(); Ast_Lambda *result = ast_lambda(token, params, parse_optional_type()); return result; } @@ -196,7 +208,7 @@ null_denotation(Token *token){ case TK_StringLit : return ast_expr_string(token, token->intern_val); case TK_Identifier: return ast_expr_identifier(token, token->intern_val); case TK_Integer : return ast_expr_integer(token, token->int_val); - case TK_BitXor : return ast_expr_unary(token, TK_Dereference, parse_expr()); + case TK_Pointer : return ast_expr_unary(token, TK_Dereference, parse_expr()); case TK_Keyword: { if(token->intern_val == keyword_cast){ token_expect(TK_OpenParen); @@ -207,7 +219,7 @@ null_denotation(Token *token){ return ast_expr_cast(token, expr, typespec); } else { - parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str); + parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str); return 0; } }break; @@ -216,8 +228,8 @@ null_denotation(Token *token){ if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token); else if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token); else{ - Ast_Expr *result = parse_expr(); - token_expect(TK_CloseParen); + Ast_Expr *result = parse_expr(); + token_expect(TK_CloseParen); return result; } } @@ -226,18 +238,18 @@ null_denotation(Token *token){ } function S64 -left_binding_power(Token_Kind kind){ +left_binding_power(Token_Kind kind){ switch(kind){ - case TK_Sub: case TK_Add: return 1; - case TK_Mul: case TK_Div: return 2; + case TK_Sub: case TK_Add: return 1; + case TK_Mul: case TK_Div: return 2; default: return 0; } } function S64 -postfix_binding_power(Token_Kind kind){ +postfix_binding_power(Token_Kind kind){ switch(kind){ - case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1; + case TK_Increment: case TK_Decrement: case TK_Pointer: case TK_OpenBracket: return 1; default: return 0; } } @@ -259,11 +271,11 @@ parse_expr(S64 rbp){ Ast_Expr *left = null_denotation(token); for(;;){ token = token_get(); - - if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_BitXor || token->kind == TK_OpenBracket)){ + + if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_Pointer || token->kind == TK_OpenBracket)){ token_next(); if(token->kind == TK_OpenBracket){ - Ast_Expr *index = parse_expr(); + Ast_Expr *index = parse_expr(); left = ast_expr_index(token, left, index); token_expect(TK_CloseBracket); } @@ -273,13 +285,13 @@ parse_expr(S64 rbp){ left = ast_expr_unary(token, token->kind, left); } } - + else if(rbp < left_binding_power(token->kind)){ token = token_next(); left = left_denotation(token, left); } else break; - + } return left; } @@ -312,11 +324,11 @@ expr_eval(Ast_Expr *expr){ return 0; } -#define TEST_PARSER() \ -Scratch scratch(thread_ctx.scratch);\ -Parse_Ctx ctx = {}; \ -ctx.init(scratch, scratch); \ -pctx = &ctx +#define TEST_PARSER() \ + Scratch scratch(thread_ctx.scratch); \ + Parse_Ctx ctx = {}; \ + ctx.init(scratch, scratch); \ + pctx = &ctx function void test_parse_expr(){ @@ -329,8 +341,8 @@ test_parse_expr(){ exprs.add({"4+5*2"_s, 4+5*2}); exprs.add({"4*5+5"_s, 4*5+5}); exprs.add({"4+5+5+3"_s, 4+5+5+3}); - - Iter(exprs){ + + For(exprs){ lex_restream(&ctx, it->str, "test_expr"_s); Ast_Expr *result = parse_expr(); S64 val = expr_eval(result); @@ -341,12 +353,11 @@ test_parse_expr(){ //----------------------------------------------------------------------------- // Parsing declarations //----------------------------------------------------------------------------- - // [10]*int - Array of 10 pointers to ints function Ast_Typespec * parse_typespec_recurse(){ Token *token = token_get(); - if(token_match(TK_BitXor)){ + if(token_match(TK_Pointer)){ Ast_Typespec *result = parse_typespec_recurse(); result = ast_typespec_pointer(token, result); return result; @@ -395,20 +406,20 @@ parse_decl(){ Ast_Expr *expr = parse_expr(); result = ast_decl_const(name, name->intern_val, expr); } - else if(token_match(TK_Colon)){ + else if(token_match(TK_Colon)){ Ast_Typespec *typespec = 0; Ast_Expr *expr = 0; if(!token_is(TK_Assign)) typespec = parse_typespec(); if(token_match(TK_Assign)) expr = parse_expr(); if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value"); - + result = ast_decl_var(name, typespec, name->intern_val, expr); } else{ Token *token = token_get(); parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str); } - + } return result; } diff --git a/new_resolve.cpp b/new_resolve.cpp index 4e7590c..4cfdf11 100644 --- a/new_resolve.cpp +++ b/new_resolve.cpp @@ -1,4 +1,4 @@ -#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast; +#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast; #define Ast_End() } break enum Sym_Kind{ @@ -12,7 +12,7 @@ struct Sym{ Intern_String name; Sym_Kind kind; Ast_Decl *decl; - Type *type; + Ast_Resolved_Type *type; union{ S64 int_val; Intern_String intern_val; @@ -20,7 +20,7 @@ struct Sym{ }; struct Operand{ - Type *type; + Ast_Resolved_Type *type; bool is_const; union { S64 int_val; @@ -33,9 +33,9 @@ sym_insert(Sym *sym){ U64 hash = hash_string(sym->name.s); Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash); if(is_sym){ - parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); + parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); } - + map_insert_u64(&pctx->global_syms, hash, sym); } @@ -46,7 +46,7 @@ sym_get(Intern_String name){ } function Sym * -sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){ +sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast_Decl *decl){ Sym *result = exp_alloc_type(pctx->perm, Sym); result->name = name; result->kind = kind; @@ -57,7 +57,7 @@ sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){ global Ast_Decl empty_decl = {}; function void -sym_insert_builtin_type(String name, Type *type){ +sym_insert_builtin_type(String name, Ast_Resolved_Type *type){ Intern_String string = intern_string(&pctx->interns, name); Sym *sym = sym_new(SYM_Type, string, type, &empty_decl); sym_insert(sym); @@ -69,33 +69,31 @@ sym_insert_builtins(){ sym_insert_builtin_type("bool"_s, type_bool); sym_insert_builtin_type("int"_s, type_int); sym_insert_builtin_type("String"_s, type_string); - + { Intern_String string = intern_string(&pctx->interns, "true"_s); Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl); sym_insert(sym); } - + { Intern_String string = intern_string(&pctx->interns, "false"_s); Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl); sym_insert(sym); } - + { Intern_String string = intern_string(&pctx->interns, "null"_s); Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl); sym_insert(sym); } - - } -function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0); -function Type * +function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0); +function Ast_Resolved_Type * eval_typespec(Ast_Typespec *ast){ if(!ast) return 0; - + switch(ast->kind){ Ast_Begin(AST_TYPESPEC_IDENT, Ast_Typespec){ Sym *type_sym = sym_get(node->name); @@ -105,34 +103,36 @@ eval_typespec(Ast_Typespec *ast){ if(type_sym->kind != SYM_Type){ parsing_error(node->pos, "This identifier is not a type"); } - return type_sym->type; + + node->resolved_type = type_sym->type; + return node->resolved_type; Ast_End(); } - + Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){ Scratch scratch; - Type *ret = eval_typespec(node->lambda->ret); - Array params = {scratch}; + Ast_Resolved_Type *ret = eval_typespec(node->lambda->ret); + Array params = {scratch}; For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec)); - Type *result = type_lambda(ret, params); - return result; + node->resolved_type = type_lambda(ret, params); + return node->resolved_type; Ast_End(); } - + Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){ - Type *type = eval_typespec(node->base); - Type *result = type_pointer(type); - return result; + Ast_Resolved_Type *type = eval_typespec(node->base); + node->resolved_type = type_pointer(type); + return node->resolved_type; Ast_End(); } - + Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){ - Type *type = eval_typespec(node->arr.base); + Ast_Resolved_Type *type = eval_typespec(node->arr.base); Operand expr = eval_expr(node->arr.expr); if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant"); - if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type int"); - Type *result = type_array(type, expr.int_val); - return result; + if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type [Int] is instead of type %s", type_names[expr.type->kind]); + node->resolved_type = type_array(type, expr.int_val); + return node->resolved_type; Ast_End(); } invalid_default_case; @@ -140,43 +140,94 @@ eval_typespec(Ast_Typespec *ast){ return 0; } -function Type * -resolve_type_pair(Token *pos, Type *a, Type *b){ - Type *result = 0; +function Ast_Resolved_Type * +resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){ + Ast_Resolved_Type *result = 0; if(!a && b) result = b; else if(a && !b) result = a; - else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are null"); + else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]"); else{ // a && b if(b->kind == TYPE_Null) result = a; else if(a->kind == TYPE_Null) result = b; - else if(a != b) parsing_error(pos, "Expression and type specification are differing"); + else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]); else result = a; // Types are the same } - + + if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value"); + return result; } -function Operand -eval_expr(Ast_Expr *ast, Type *exp_compound_type){ +function Operand +eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){ switch(ast->kind){ Ast_Begin(AST_INT, Ast_Expr){ Operand result = {type_int, true, {.int_val=(S64)node->int_val}}; return result; Ast_End(); } - + Ast_Begin(AST_STR, Ast_Expr){ Operand result = {type_string, true, {.intern_val = node->intern_val}}; return result; Ast_End(); } - + + Ast_Begin(AST_IDENT, Ast_Expr){ + Sym *sym = sym_get(node->intern_val); + if(!sym){ + parsing_error(node->pos, "Identifier is undefined"); + } + + // @note: check if null and rewrite the expression to match the expected type + Operand result = {}; + if(sym->type->kind == TYPE_Null){ + if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null"); + result.type = expected_type; + result.is_const = true; + if(expected_type == type_int){ + result.int_val = 0; + node->kind = AST_INT; + node->int_val = 0; + } + else if(expected_type->kind == TYPE_Pointer){ + result.int_val = 0; + node->kind = AST_IDENT; + node->intern_val = pctx->intern("null_pointer"_s); + } + else if(expected_type->kind == TYPE_Lambda){ + result.int_val = 0; + node->kind = AST_IDENT; + node->intern_val = pctx->intern("null_lambda"_s); + } + else if(expected_type == type_bool){ + result.int_val = 0; + node->kind = AST_IDENT; + node->intern_val = pctx->intern("false"_s); + } + else if(expected_type == type_string){ + result.intern_val = pctx->intern(""_s); + node->kind = AST_STR; + node->intern_val = result.intern_val; + } + + } + else{ + result.type = sym->type; + result.is_const = sym->kind == SYM_Const ? true : false; + result.int_val = sym->int_val; + } + + return result; + Ast_End(); + } + Ast_Begin(AST_LAMBDA, Ast_Lambda){ - Type *type = eval_typespec(ast_typespec_lambda(0, node)); + Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node)); return {type, true}; Ast_End(); } - + Ast_Begin(AST_INDEX, Ast_Expr){ Operand left = eval_expr(node->index.expr); Operand index = eval_expr(node->index.index); @@ -186,81 +237,71 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){ return result; Ast_End(); } - + Ast_Begin(AST_COMPOUND, Ast_Expr){ - Type *type = eval_typespec(node->compound.typespec); - Type *variable_type = exp_compound_type; + Ast_Resolved_Type *type = eval_typespec(node->compound.typespec); + Ast_Resolved_Type *variable_type = expected_type; if(!type && variable_type) type = variable_type; else if(!variable_type && type); else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type"); - + node->compound.type = type; + if(type->kind == TYPE_Array){ if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type"); - Type *item_type = type->arr.base; - + Ast_Resolved_Type *item_type = type->arr.base; + For(node->compound.exprs){ assert(it[0]->kind == AST_COMPOUND_ITEM); Ast_Expr *i = (Ast_Expr *)it[0]; assert(i->kind == AST_COMPOUND_ITEM); - if(i->compound_item.name) parsing_error(i->pos, "Invalid array indexing in compound expression"); + if(i->compound_item.name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]); if(i->compound_item.index){ Operand index_op = eval_expr(i->compound_item.index); if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant"); if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int"); if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store"); } - Operand expr = eval_expr(i->compound_item.item); + Operand expr = eval_expr(i->compound_item.item, item_type); resolve_type_pair(i->pos, expr.type, item_type); } } else parsing_error(node->pos, "Invalid compound expression type"); - + Operand result = {type, false}; return result; Ast_End(); } - - Ast_Begin(AST_IDENT, Ast_Expr){ - Sym *sym = sym_get(node->intern_val); - if(!sym){ - parsing_error(node->pos, "Identifier is undefined"); - } - - Operand result = {sym->type, sym->kind == SYM_Const ? true : false, {.int_val = sym->int_val}}; - return result; - Ast_End(); - } - + Ast_Begin(AST_CAST, Ast_Expr){ Operand expr = eval_expr(node->cast.expr); - Type *type = eval_typespec(node->cast.typespec); - + Ast_Resolved_Type *type = eval_typespec(node->cast.typespec); + if(type == expr.type) return expr; - + else if(expr.type == type_int && type == type_bool){ expr.type = type_bool; return expr; } - + else if(expr.type == type_bool && type == type_int){ expr.type = type_int; return expr; } - + else if(expr.type == type_null){ expr.type = type; return expr; } - + else parsing_error(node->pos, "Failed to cast, incompatible types"); - + Ast_End(); } - + Ast_Begin(AST_UNARY, Ast_Expr){ Operand value = eval_expr(node->unary.expr); switch(node->unary.op){ - case TK_BitXor:{ + case TK_Pointer:{ if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer"); Operand result = {value.type->base}; return result; @@ -271,10 +312,10 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){ }break; invalid_default_case; return {}; } - + Ast_End(); } - + Ast_Begin(AST_BINARY, Ast_Expr){ Operand left = eval_expr(ast->binary.left); Operand right = eval_expr(ast->binary.right); @@ -293,51 +334,51 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){ } else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported"); } - + return result; Ast_End(); } - + invalid_default_case; } - + return {}; } function void eval_decl(Ast *ast){ switch(ast->kind){ - + Ast_Begin(AST_PACKAGE, Ast_Package){ For(node->decls) eval_decl(*it); Ast_End(); } - + Ast_Begin(AST_VAR, Ast_Decl){ - Type *type = eval_typespec(node->var.typespec); + Ast_Resolved_Type *type = eval_typespec(node->var.typespec); Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{}; - Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); - + Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); + Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node); sym_insert(sym); Ast_End(); } - + Ast_Begin(AST_CONST, Ast_Decl){ - Type *type = eval_typespec(node->var.typespec); + Ast_Resolved_Type *type = eval_typespec(node->var.typespec); if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer"); Operand expr = eval_expr(node->var.expr); 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"); - Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); - + Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); + Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node); if(resolved_type == type_int) sym->int_val = expr.int_val; else if(resolved_type == type_string) sym->intern_val = expr.intern_val; sym_insert(sym); Ast_End(); } - + invalid_default_case; } } diff --git a/new_type.cpp b/new_type.cpp index 06c1323..dd8a220 100644 --- a/new_type.cpp +++ b/new_type.cpp @@ -1,4 +1,4 @@ -enum Type_Kind{ +enum Ast_Resolved_Type_Kind{ TYPE_None, TYPE_Null, TYPE_Int, @@ -8,41 +8,41 @@ enum Type_Kind{ TYPE_Void, TYPE_Pointer, TYPE_Array, - TYPE_Func, + TYPE_Lambda, TYPE_Struct, TYPE_Union, TYPE_Enum, }; const char *type_names[] = { - "[Invalid Type]", - "[TYPE_Null]", - "[TYPE_Int]", - "[TYPE_Bool]", - "[TYPE_Unsigned]", - "[TYPE_String]", - "[TYPE_Void]", - "[TYPE_Pointer]", - "[TYPE_Array]", - "[TYPE_Func]", - "[TYPE_Struct]", - "[TYPE_Union]", - "[TYPE_Enum]", + "[Invalid Ast_Resolved_Type]", + "[Null]", + "[Int]", + "[Bool]", + "[Unsigned]", + "[String]", + "[Void]", + "[Pointer]", + "[Array]", + "[Lambda]", + "[Struct]", + "[Union]", + "[Enum]", }; -struct Type{ - Type_Kind kind; +struct Ast_Resolved_Type{ + Ast_Resolved_Type_Kind kind; SizeU size; SizeU align; union{ - Type *base; + Ast_Resolved_Type *base; struct{ - Type *base; + Ast_Resolved_Type *base; SizeU size; }arr; struct{ - Type *ret; - Array args; + Ast_Resolved_Type *ret; + Array args; }func; }; }; @@ -50,39 +50,39 @@ struct Type{ const SizeU pointer_size = sizeof(SizeU); const SizeU pointer_align = __alignof(SizeU); -global Type type__null = {TYPE_Null}; -global Type type__void = {TYPE_Void}; -global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)}; -global Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)}; -global Type type__string = {TYPE_String, sizeof(String), __alignof(String)}; -global Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)}; +global Ast_Resolved_Type type__null = {TYPE_Null}; +global Ast_Resolved_Type type__void = {TYPE_Void}; +global Ast_Resolved_Type type__int = {TYPE_Int, sizeof(int), __alignof(int)}; +global Ast_Resolved_Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)}; +global Ast_Resolved_Type type__string = {TYPE_String, sizeof(String), __alignof(String)}; +global Ast_Resolved_Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)}; -global Type *type_void = &type__void; -global Type *type_int = &type__int; -global Type *type_unsigned = &type__unsigned; -global Type *type_string = &type__string; -global Type *type_bool = &type__bool; -global Type *type_null = &type__null; +global Ast_Resolved_Type *type_void = &type__void; +global Ast_Resolved_Type *type_int = &type__int; +global Ast_Resolved_Type *type_unsigned = &type__unsigned; +global Ast_Resolved_Type *type_string = &type__string; +global Ast_Resolved_Type *type_bool = &type__bool; +global Ast_Resolved_Type *type_null = &type__null; -function Type * -type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){ - Type *result = exp_alloc_type(allocator, Type); +function Ast_Resolved_Type * +type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){ + Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type); result->kind = kind; result->size = size; result->align = align; return result; } -function Type * -type_copy(Allocator *a, Type *type){ - Type *result = exp_alloc_type(a, Type); - memory_copy(result, type, sizeof(Type)); +function Ast_Resolved_Type * +type_copy(Allocator *a, Ast_Resolved_Type *type){ + Ast_Resolved_Type *result = exp_alloc_type(a, Ast_Resolved_Type); + memory_copy(result, type, sizeof(Ast_Resolved_Type)); return result; } -function Type * -type_pointer(Type *base){ - Type *result = (Type *)map_get(&pctx->type_map, (void *)base); +function Ast_Resolved_Type * +type_pointer(Ast_Resolved_Type *base){ + Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base); if(!result){ result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align); result->base = base; @@ -92,17 +92,17 @@ type_pointer(Type *base){ return result; } -function Type * -type_array(Type *base, SizeU size){ +function Ast_Resolved_Type * +type_array(Ast_Resolved_Type *base, SizeU size){ U64 hash = hash_mix(hash_ptr(base), hash_u64(size)); - Type *result = (Type *)map_get_u64(&pctx->type_map, hash); + Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash); if(result){ assert(result->kind == TYPE_Array); assert(result->arr.size == size); assert(result->arr.base == base); return result; } - + result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align); result->arr.base = base; result->arr.size = size; @@ -110,24 +110,24 @@ type_array(Type *base, SizeU size){ return result; } -function Type * -type_lambda(Type *ret, Array args){ +function Ast_Resolved_Type * +type_lambda(Ast_Resolved_Type *ret, Array args){ U64 hash = hash_ptr(ret); For(args) hash = hash_mix(hash, hash_ptr(*it)); - Type *result = (Type *)map_get_u64(&pctx->type_map, hash); - + Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash); + if(result){ - assert(result->kind == TYPE_Func); + assert(result->kind == TYPE_Lambda); assert(result->func.ret == ret); assert(result->func.args.len == args.len); return result; } - - result = type_new(pctx->perm, TYPE_Func, pointer_size, pointer_align); + + result = type_new(pctx->perm, TYPE_Lambda, pointer_size, pointer_align); result->func.ret = ret; result->func.args = args.tight_copy(pctx->perm); map_insert_u64(&pctx->type_map, hash, result); - + return result; } @@ -137,34 +137,34 @@ test_types(){ Parse_Ctx ctx = {}; ctx.init(scratch, scratch); pctx = &ctx; - - Type *array_type1 = type_array(type_int, 32); - Type *array_type2 = type_array(type_int, 32); - Type *array_type3 = type_array(type_int, 48); + + Ast_Resolved_Type *array_type1 = type_array(type_int, 32); + Ast_Resolved_Type *array_type2 = type_array(type_int, 32); + Ast_Resolved_Type *array_type3 = type_array(type_int, 48); assert(array_type1 == array_type2); assert(array_type2 != array_type3); - Type *pointer_type1 = type_pointer(type_int); - Type *pointer_type2 = type_pointer(type_int); + Ast_Resolved_Type *pointer_type1 = type_pointer(type_int); + Ast_Resolved_Type *pointer_type2 = type_pointer(type_int); assert(pointer_type2 == pointer_type1); - Type *pointer_type3 = type_pointer(pointer_type1); - Type *pointer_type4 = type_pointer(pointer_type2); + Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1); + Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2); assert(pointer_type3 != pointer_type1); assert(pointer_type3 == pointer_type4); - - Array types = {scratch}; + + Array types = {scratch}; types.add(type_array(type_int, 32)); - Type *func_type1 = type_lambda(types[0], types); - Type *func_type2 = type_lambda(types[0], types); + Ast_Resolved_Type *func_type1 = type_lambda(types[0], types); + Ast_Resolved_Type *func_type2 = type_lambda(types[0], types); assert(func_type1 == func_type2); - - Array types2 = {scratch}; + + Array types2 = {scratch}; { types2.add(type_array(type_int, 32)); types2.add(type_int); } types.add(type_int); - Type *func_type3 = type_lambda(types[0], types); - Type *func_type4 = type_lambda(types[0], types2); + Ast_Resolved_Type *func_type3 = type_lambda(types[0], types); + Ast_Resolved_Type *func_type4 = type_lambda(types[0], types2); assert(func_type1 != func_type3); assert(func_type3 == func_type4); } diff --git a/output.cc b/output.cc deleted file mode 100644 index 11ef992..0000000 --- a/output.cc +++ /dev/null @@ -1,294 +0,0 @@ -(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2))) -(4+(2*53)) -((4+2)*53) -(++5) -(--5) -(-5) -(+5) -(sizeof(32)+sizeof(S32*)) -((S64**)5) -(((S64)5)+3) -((534>43)?435:42) -struct Thing{ -int test; -}; - -S32 thing = 100; -(thing=(thing+10)); -(++thing); -{ -S32 thing_scoped = 10; -(thing_scoped+=10); -} -typedef struct OpenGL OpenGL; -typedef struct OS_Memory OS_Memory; -typedef struct Arena Arena; -typedef struct String String; -typedef struct Token Token; -typedef struct Lex_Stream Lex_Stream; -typedef struct Expr Expr; -typedef struct AST_Node AST_Node; -typedef struct Parser_Error Parser_Error; -typedef struct Scope Scope; -typedef struct Parser Parser; -struct test{ -struct Array_Block{ -Array_Block (*next); -Based_Type_Represent (data[size]); -}; - -struct Array{ -Array_Block first; -Array_Block (*last); -S64 block; -S64 len; -}; - -function Based_Type_Represent array_make(Arena (*arena)){ -Test_Type thing; -Based_Type_Represent result; -((result.arena)=arena); -((result.last)=(&(result.first))); -return result; -} -function void array_push(Array (*array), Based_Type_Represent (*item)){ -if (((array->len)+1)>size){ -assert((array->len)); -Array_Block (*block) = ((Thing)arena_push_struct(((array->arena),sizeof(Array_Block)))); -((array->last)=(((array->last).next)=block)); -((array->len)=0); -((array->block)+=1); -} -(((array->last).data)[(++(array->len))]=(*item)); -} -}; - -struct OpenGL{ -void (*glVertexAttribPointer)(GLuint, GLint, GLenumGLenum, GLboolean, GLsizei, GLvoid *); -void (*glBindTexture)(GLenum, GLuint); -void (*glDrawArrays)(GLenumGLenum, GLint, GLsizei); -int (*(test_array[10])); -Things (*thing); -S64 thing_cap; -S64 thing_len; -}; - -struct OS_Memory{ -void (*data); -SizeU commit; -SizeU reserve; -}; - -struct Arena{ -OS_Memory memory; -U64 len; -U64 alignment; -}; - -struct String{ -U8 (*str); -S64 len; -}; - -typedef String Intern_String; -typedef enum Token_Kind{ -TK_End, -TK_Mul, -TK_Div, -TK_Add, -TK_Sub, -TK_Mod, -TK_BitAnd, -TK_BitOr, -TK_BitXor, -TK_Neg, -TK_Not, -TK_OpenParen, -TK_CloseParen, -TK_OpenBrace, -TK_CloseBrace, -TK_OpenBracket, -TK_CloseBracket, -TK_Comma, -TK_Pound, -TK_Question, -TK_ThreeDots, -TK_Semicolon, -TK_Dot, -TK_LesserThen, -TK_GreaterThen, -TK_Colon, -TK_Assign, -TK_DivAssign, -TK_MulAssign, -TK_ModAssign, -TK_SubAssign, -TK_AddAssign, -TK_AndAssign, -TK_OrAssign, -TK_XorAssign, -TK_LeftShiftAssign, -TK_RightShiftAssign, -TK_DoubleColon, -TK_At, -TK_Decrement, -TK_Increment, -TK_PostDecrement, -TK_PostIncrement, -TK_LesserThenOrEqual, -TK_GreaterThenOrEqual, -TK_Equals, -TK_And, -TK_Or, -TK_NotEquals, -TK_LeftShift, -TK_RightShift, -TK_Arrow, -TK_ExprSizeof, -TK_DocComment, -TK_Comment, -TK_Identifier, -TK_StringLit, -TK_U8Lit, -TK_Character, -TK_Error, -TK_Float, -TK_Int, -TK_Keyword, -}Token_Kind; - -struct Token{ -Token_Kind kind; -String string; -union{ -S64 integer_val; -String error_val; -Intern_String intern_val; -}; -String file; -S64 line; -U8 (*line_begin); -}; - -struct Lex_Stream{ -U8 (*stream); -U8 (*line_begin); -String filename; -S64 line; -}; - -typedef enum Expr_Kind{ -EK_None, -EK_Atom, -EK_Unary, -EK_Binary, -EK_Ternary, -EK_Cast, -EK_List, -EK_Call, -EK_Index, -}Expr_Kind; - -struct Expr{ -Expr_Kind kind; -Token (*token); -Expr (*next); -union{ -struct{ -AST_Node (*type); -Expr (*expr); -}cast_val; -struct{ -Expr (*first); -Expr (*last); -}list; -struct{ -Expr (*atom); -Expr (*list); -}call; -struct{ -Expr (*atom); -Expr (*index); -}index; -struct{ -Expr (*expr); -}unary; -struct{ -Expr (*left); -Expr (*right); -}binary; -struct{ -Expr (*cond); -Expr (*on_true); -Expr (*on_false); -}ternary; -}; -}; - -typedef enum AST_Kind{ -AK_None, -AK_BaseType, -AK_Typedef, -AK_Enum, -AK_Struct, -AK_Union, -AK_Note, -AK_List, -AK_Pointer, -AK_Array, -AK_Function, -AK_Variable, -AK_EnumChild, -}AST_Kind; - -struct AST_Node{ -AST_Kind kind; -Token (*pos); -Intern_String name; -AST_Node (*next); -AST_Node (*next_scope); -AST_Node (*first_note); -AST_Node (*last_note); -AST_Node (*first_child); -AST_Node (*last_child); -union{ -SizeU base_type_size; -AST_Node (*pointer); -AST_Node (*typedef_type); -AST_Node (*variable_type); -AST_Node (*func_return_type); -}; -}; - -struct Parser_Error{ -Parser_Error (*next); -String message; -Token (*token); -}; - -struct Scope{ -Scope (*next); -AST_Node (*first); -AST_Node (*last); -}; - -struct Parser{ -Arena main_arena; -Arena intern_table_arena; -Arena symbol_table_arena; -Scope (*scope_free_list); -Scope (*scope_stack); -Scope (*global_scope); -S64 symbols_inserted; -S64 symbols_count; -AST_Node (*symbols); -Intern_String (*interns); -S64 interns_in_bytes; -S64 interns_inserted; -S64 interns_count; -U8 (*first_keyword); -U8 (*last_keyword); -Parser_Error default; -Parser_Error error; -}; - diff --git a/parse.c b/parse.c index 4653a6d..3db6dcd 100644 --- a/parse.c +++ b/parse.c @@ -9,7 +9,7 @@ struct Parser_Error{ typedef struct Parser{ Token_Array tokens; Arena *arena; - + Parser_Error *first_error; Parser_Error *last_error; }Parser; @@ -38,36 +38,36 @@ parser_push_error(Parser *p, Token *token, char *str, ...){ va_copy(args2, args1); string.len = vsnprintf(0, 0, str, args2); va_end(args2); - + string.str = arena_push_size(p->arena, string.len + 1); vsnprintf((char*)string.str, string.len + 1, str, args1); va_end(args1); } - + // @Note(Krzosa): Print nice error message printf("\nError: %s", string.str); if(token){ printf(" %s:%d\n", token->file.str, (S32)token->line); - + // @Note(Krzosa): Print error line { int i = 0; while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; printf("%.*s\n", i, token->line_begin); - + // @Note(Krzosa): Print error marker int token_i = token->str - token->line_begin; for(int i = 0; i < token_i-2; i++) printf(" "); printf("^^^^^^\n"); } } - + Parser_Error *error = arena_push_struct(p->arena, Parser_Error); error->message = string; error->next = 0; error->token = token; SLLQueuePush(p->first_error, p->last_error, error); - + __debugbreak(); } @@ -162,15 +162,15 @@ compare = == | != | >= | > | <= | < logical = [&|^] | && | || unary = [&*-!~+] | ++ | -- -atom_expr = Int -| Float -| String +atom_expr = Int +| Float +| String | Identifier | 'cast' '(' typespec ',' expr ')' | 'size_type' '(' typespec ')' | 'size_expr' '(' expr ')' | '{' compound_expr '}' -| '(' expr ')' +| '(' expr ')' | '(' ':' typespec ')' '{' compound_expr '}' postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* unary_expr = unary ? unary_expr : atom_expr @@ -205,7 +205,7 @@ parse_expr_compound_field(Parser *p){ parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value"); } result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p)); - + } else{ result = expr_compound_default(p->arena, token, expr); @@ -251,7 +251,7 @@ parse_expr_atom(Parser *p){ else if(token_is(p, TK_OpenBrace)){ result = parse_expr_compound(p, 0); } - + else if(token_match(p, TK_OpenParen)){ if(token_match(p, TK_Colon)){ Typespec *typespec = parse_typespec(p); @@ -343,7 +343,7 @@ parse_expr_postfix(Parser *p){ function B32 token_is_unary(Parser *p){ Token *token = token_get(p); - B32 result = token->kind == TK_Add + B32 result = token->kind == TK_Add || token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_Sub @@ -462,15 +462,15 @@ parse_expr(Parser *p){ // Type specifier parsing //----------------------------------------------------------------------------- /* - base_type = NAME + base_type = NAME | '(' type_list? ')' type? type = ('*' | '[' expr ']')* base_type -Examples: +Examples: [32]*U32 - Array of 32 pointers to U32 **CustomDataType - Pointer to pointer of CustomDataType -(*U32, S64) **S64 - Function pointer +(*U32, S64) **S64 - Function pointer (CoolType: optional, S32) - Implicit void return value */ @@ -490,9 +490,9 @@ parse_optional_type(Parser *p, Intern_String type){ function Typespec * parse_typespec_function(Parser *p, Token *token){ Typespec *result = typespec_function(p->arena, token, 0); - if(!token_is(p, TK_CloseParen)) + if(!token_is(p, TK_CloseParen)) for(;;) { - + // Optional name Token *name = 0; if((token = token_is(p, TK_Identifier))){ @@ -502,21 +502,21 @@ parse_typespec_function(Parser *p, Token *token){ name = token; } } - + // Parse type Typespec *arg = parse_typespec(p); - if(name) + if(name) arg = typespec_named_argument(p->arena, name, arg, name->intern_val); typespec_function_push(result, arg); - + if(!token_match(p, TK_Comma)){ break; } } token_expect(p, TK_CloseParen); - + result->func.ret = parse_optional_type(p, intern_void); - + return result; } @@ -578,7 +578,7 @@ name::const = 4254; // } // } */ -function void +function void parse_note_list(Parser *p, AST_Parent *parent) { if(token_match(p, TK_OpenParen)) { if(token_match(p, TK_CloseParen)){ @@ -596,7 +596,7 @@ parse_note_list(Parser *p, AST_Parent *parent) { } } -function void +function void parse__notes(Parser *p, AST_Parent *result) { while(token_match(p, TK_At)) { Token *name = token_expect(p, TK_Identifier); @@ -791,7 +791,7 @@ parse_decl(Parser *p, AST_Parent *parent){ "token '%s'", token_kind_string[token->kind]); } } - + if(result){ result->notes = note; ast_push_last(parent, result); @@ -806,7 +806,7 @@ parse_decl(Parser *p, AST_Parent *parent){ function AST *parse_stmt(Parser *p); /* stmt_list = '{' stmt* '}' -stmt = +stmt = | stmt_list | 'return' expr ';' | 'if' expr stmt_list @@ -969,11 +969,11 @@ parse_stmt(Parser *p){ result = parse_simple_stmt(p); token_expect(p, TK_Semicolon); } - + if(result){ result->notes = notes; } - + return result; } @@ -1017,7 +1017,7 @@ eval_expr(Expr *expr){ case TK_LesserThen: return left < right; break; case TK_BitAnd: return left & right; break; case TK_BitOr: return left | right; break; - case TK_BitXor: return left ^ right; break; + case TK_Pointer: return left ^ right; break; case TK_And: return left && right; break; case TK_Or: return left || right; break; case TK_LeftShift: return left << right; break; @@ -1083,11 +1083,11 @@ parse_test_expr(){ " 1>5 ? 1 : 2 " " !!!!!1 " " ~~1 + -!2 " - " 1 + ++Thing[12]++ + ++Thing[12].expr +" + " 1 + ++Thing[12]++ + ++Thing[12].expr +" ); Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr")); Parser *p = &parser; - + S64 t = 5; S64 test_val[] = { (32+52-242*2/424%5-23), @@ -1106,7 +1106,7 @@ parse_test_expr(){ S64 val = eval_expr(expr); assert(val == test_val[i]); } - + String exprs[] = { lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"), lit("cast((thing: U32, qwe: *U32), (123+234))"), @@ -1123,7 +1123,7 @@ parse_test_expr(){ expr_print(expr); printf("\n"); } - + arena_end_scratch(); } @@ -1131,7 +1131,7 @@ function void parse_test_decls(){ Arena *scratch = arena_begin_scratch(); Parser p = parser_make(scratch); - + String decls[] = { lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"), lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"), @@ -1156,7 +1156,7 @@ parse_test_from_file(){ arena_end_scratch(); } -function void +function void parse_test_stmt(){ Arena *scratch = arena_begin_scratch(); Parser p = parser_make(scratch); diff --git a/test.cc b/test.cc deleted file mode 100644 index 2b9aaca..0000000 --- a/test.cc +++ /dev/null @@ -1,286 +0,0 @@ -Thing :: const: *U32 = 0; -CONST_VAL::const = 185210591; -new_function::(Thing:[32]U32): U32; - -@test(size = 4096) -OpenGL :: struct{ - glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, *GLvoid); - glBindTexture: (GLenum, GLuint); - glDrawArrays: (GLenum, GLint, GLsizei); - - test_array: [10]*int; - - thing : *Things; - thing_cap: S64; - thing_len: S64; -} - -OS_Memory::struct{ - data: *void; - commit: SizeU; - reserve: SizeU; -} - -Arena::struct{ - @using memory: OS_Memory; - len: U64; - alignment: U64; -} - -String::struct{ - str: *U8; - len: S64; -} -Intern_String::typedef = String; -//CONST_VALUE::const = 121591; - -@stringify -@prefix="TK_" -Token_Kind::enum{ - @str="End of stream" End, - @str="*" Mul, - @str="/" Div, - @str="+" Add, - @str="-" Sub, - @str="%" Mod, - @str="&" BitAnd, - @str="|" BitOr, - @str="^" BitXor, - @str="~" Neg, - @str="!" Not, - @str="(" OpenParen, - @str=" " CloseParen, - @str="{" OpenBrace, - @str="}" CloseBrace, - @str="[" OpenBracket, - @str="]" CloseBracket, - @str="," Comma, - @str="#" Pound, - @str="?" Question, - @str="..." ThreeDots, - @str=";" Semicolon, - @str="." Dot, - @str="<" LesserThen, - @str=">" GreaterThen, - @str=":" Colon, - @str="=" Assign, - @str="/=" DivAssign, - @str="*=" MulAssign, - @str="%=" ModAssign, - @str="-=" SubAssign, - @str="+=" AddAssign, - @str="&=" AndAssign, - @str="|=" OrAssign, - @str="^=" XorAssign, - @str="<<=" LeftShiftAssign, - @str=">>=" RightShiftAssign, - @str="::" DoubleColon, - @str="@" At, - @str="--" Decrement, - @str="++" Increment, - @str="--" PostDecrement, - @str="++" PostIncrement, - @str="<=" LesserThenOrEqual, - @str=">=" GreaterThenOrEqual, - @str="==" Equals, - @str="&&" And, - @str="||" Or, - @str="!=" NotEquals, - @str="<<" LeftShift, - @str=">>" RightShift, - @str="->" Arrow, - @str="sizeof" ExprSizeof, - DocComment, - Comment, - Identifier, - StringLit, - U8Lit, - Character, - Error, - Float, - Int, - Keyword, -} - -@array(type=block) -Token::struct{ - kind:Token_Kind; - @using string:String; - union{ - integer_val:S64; - error_val:String; - intern_val:Intern_String; - } - file:String; - line:S64; - line_begin:*U8; -} - -Lex_Stream::struct{ - stream: *U8; - line_begin: *U8; - filename: String; - line: S64; -} - -@prefix="EK_" -Expr_Kind::enum{ - None, - Atom, - Unary, - Binary, - Ternary, - Cast, - List, - Call, - Index, -} - -Expr:: struct{ - kind: Expr_Kind; - token: *Token; - next : *Expr; - union{ - cast_val: struct{ - type: *AST_Node; - expr: *Expr; - } - list: struct{ - first: *Expr; - last: *Expr; - } - call: struct{ - atom: *Expr; - list: *Expr; - } - index: struct{ - atom: *Expr; - index: *Expr; - } - unary: struct{ - expr: *Expr ; - } - binary: struct{ - left: *Expr ; - right: *Expr ; - } - ternary: struct{ - cond: *Expr ; - on_true: *Expr; - on_false: *Expr; - } - } -} - -@prefix="AK_" -AST_Kind::enum{ - None, - BaseType, - Typedef, - Enum, - Struct, - Union, - Note, - List, - Pointer, - Array, - Function, - Variable, - EnumChild, -} - -AST_Node::struct{ - kind: AST_Kind; - pos : *Token; - name: Intern_String; - - next: *AST_Node; - next_scope: *AST_Node; - - first_note: *AST_Node; - last_note: *AST_Node; - - first_child: *AST_Node; - last_child: *AST_Node; - union{ - base_type_size: SizeU; - pointer: *AST_Node; - typedef_type: *AST_Node; - variable_type: *AST_Node; - func_return_type: *AST_Node; - } -} - -Parser_Error :: struct{ - next: *Parser_Error; - message: String; - token : *Token; -} - -Scope :: struct{ - next : *Scope; - first: *AST_Node; - last : *AST_Node; -} - - -Parser :: struct{ - main_arena: Arena; - intern_table_arena: Arena; - symbol_table_arena: Arena; - - scope_free_list: Scope; - scope_stack: Scope; - global_scope: Scope; - - symbols_inserted: S64; - symbols_count: S64; - symbols: AST_Node; - - interns: Intern_String; - interns_in_bytes: S64; - interns_inserted: S64; - interns_count: S64; - - first_keyword: U8; - last_keyword: U8; - - //@map(type="sparse") symbols: AST_Node; - - // @Todo(Krzosa): This adds default to function name currently - // And it's hard to anything else sort of except adding - // a variable of _var_name_lower_with_ or something - @sllqueue default: Parser_Error; - - // This works ok - @sllqueue error: Parser_Error; - //@using token_array: Tokens; -} - - -function_test::(a:U32, b:U32):*U32{ - scratch := get_scratch(); - defer{release_scratch(scratch);} - if a > 10 { - c := b + 10; - b = c; - } - else if a == 20 { - d := 1241215; - b = d; - } - else { - c := b+20; - b = c; - } - - for { - c: U32 = b + 1; - } - - for i:=0; i < 10; i++ { - print(i); - } - - return *b; -} diff --git a/test2.cc b/test2.cc deleted file mode 100644 index 7c41c7f..0000000 --- a/test2.cc +++ /dev/null @@ -1,31 +0,0 @@ - -Thing :: struct { - arena: *Arena; -} - -main :: (argc: int, argv: **char): int { - thing: int = proc(&argc); - arena: Arena; - - for i:=0; i < 10; i++ { - - } -} - - -proc :: (thing: *int): *int { - thing = SCRATCH_COUNT + 10; - return thing; -} - -Arena :: struct { - cap: int; - len: int; - data: *void; -} - -Thread_Ctx :: struct { - arenas: [SCRATCH_COUNT]Arena; -} -SCRATCH_COUNT::const = 3; - diff --git a/test3.kl b/test3.kl index 6a7551a..7a8d66b 100644 --- a/test3.kl +++ b/test3.kl @@ -1,7 +1,5 @@ - /* - -Player :: struct +Player :: struct id : int name: String @@ -12,7 +10,7 @@ compound_of_struct: Player = { second_compound_syntax := :Player{...} -max :: (a: int, b: int) { if a > b then return a; return b; } +max_folding :: (a: int, b: int) { if a > b { return a; } return b; } max :: (a: int, b: int) if a > b then return a @@ -22,22 +20,34 @@ max :: (a: int, b: int) { and } - treated as new line scope and end of new line scope */ +//----------------------------------------------------------------------------- +// Function types +//----------------------------------------------------------------------------- test_function :: (thing: int): ^int +function_type: (thing: int): ^int = test_function +const_function_alias :: test_function +null_function: (t: int): ^int = null //----------------------------------------------------------------------------- // Booleans //----------------------------------------------------------------------------- boolean: bool = true value_of_bool: int = cast(boolean: int) -base := null + +//----------------------------------------------------------------------------- +// Nulls +//----------------------------------------------------------------------------- +int_null: int = null +str_null: String = null +bool_null: bool = null //----------------------------------------------------------------------------- // Compound expressions //----------------------------------------------------------------------------- -array1: [4]int = {1,2,3,4} +array1: [4]int = {1,2,3,4} array2: [32]int = {1,2,3,4} -array3: [32]int = { - [0] = 0, +array3: [32]int = { + [0] = null, [1] = 1, [31] = 31, } @@ -61,8 +71,8 @@ implicit_str :: "Hello world" //----------------------------------------------------------------------------- // Pointers //----------------------------------------------------------------------------- -pointer: ^int = cast(null: ^int) -pointer2: ^int = null +pointer1: ^int = null +pointer2: ^int = pointer1 pointer3: ^^int = null //----------------------------------------------------------------------------- diff --git a/type.c b/type.c deleted file mode 100644 index e745605..0000000 --- a/type.c +++ /dev/null @@ -1,157 +0,0 @@ -typedef struct Type Type; - -typedef enum Type_Kind{ - TYPE_None, - TYPE_Incomplete, - TYPE_Int, - TYPE_Char, - TYPE_Void, - TYPE_Pointer, - TYPE_Array, - TYPE_Func, - TYPE_Struct, - TYPE_Union, - TYPE_Enum, -}Type_Kind; - -struct Type{ - Type_Kind kind; - SizeU size; - SizeU align; - struct{ - Type *base; - }pointer; - struct{ - Type *base; - SizeU size; - }array; - struct{ - Type **params; - S32 count; - Type *ret; - }func; -}; - -global Type global_type[] = { - {TYPE_Void}, - {TYPE_Int, sizeof(int), __alignof(int)}, - {TYPE_Char, sizeof(char), __alignof(char)}, -}; - -const SizeU pointer_size = sizeof(SizeU); -const SizeU pointer_align = __alignof(SizeU); - -global Type *type_void = global_type + 0; -global Type *type_int = global_type + 1; -global Type *type_char = global_type + 2; - -global Map map_pointer_types; -global Map map_array_types; -global Map map_func_types; - -function Type * -type_new(Arena *arena, Type_Kind kind, SizeU size, SizeU align){ - Type *result = arena_push_struct(arena, Type); - result->kind = kind; - result->size = size; - result->align = align; - return result; -} - -function Type * -type_copy(Arena *arena, Type *type){ - Type *result = arena_push_struct(arena, Type); - memory_copy(result, type, sizeof(Type)); - return result; -} - -function Type * -type_incomplete(Arena *arena){ - Type *result = type_new(arena, TYPE_Incomplete, 0, 0); - return result; -} - -function Type * -type_pointer(Arena *arena, Type *base){ - Type *result = map_get(&map_pointer_types, (void *)base); - if(!result){ - result = type_new(arena, TYPE_Pointer, pointer_size, pointer_align); - result->pointer.base = base; - map_insert(&map_pointer_types, base, result); - } - return result; -} - -function Type * -type_array(Arena *arena, Type *base, SizeU size){ - U64 hash = hash_mix(hash_ptr(base), hash_u64(size)); - Type *result = map_get_u64(&map_array_types, hash); - if(result){ - assert(result->array.size == size); - assert(result->array.base == base); - return result; - } - result = type_new(arena, TYPE_Array, pointer_size, pointer_align); - result->array.base = base; - result->array.size = size; - map_insert_u64(&map_array_types, hash, result); - return result; -} - -function Type * -type_lambda(Arena *arena, Type *ret, Type **params, S32 count){ - U64 hash = hash_ptr(ret); - for(S32 i = 0; i < count; i++) - hash = hash_mix(hash, hash_ptr(params[i])); - - Type *result = map_get_u64(&map_func_types, hash); - if(result){ - assert(result->func.ret == ret); - assert(result->func.count == count); - return result; - } - - result = type_new(arena, TYPE_Func, pointer_size, pointer_align); - result->func.ret = ret; - result->func.count = count; - result->func.params = arena_push_array(arena, Type*, count); - memory_copy(result->func.params, params, count); - map_insert_u64(&map_func_types, hash, result); - return result; -} - -function void -test_types(){ - Arena *arena = arena_begin_scratch(); - Type *array_type1 = type_array(arena, type_int, 32); - Type *array_type2 = type_array(arena, type_int, 32); - Type *array_type3 = type_array(arena, type_int, 48); - assert(array_type1 == array_type2); - assert(array_type2 != array_type3); - Type *pointer_type1 = type_pointer(arena, type_int); - Type *pointer_type2 = type_pointer(arena, type_int); - assert(pointer_type2 == pointer_type1); - Type *pointer_type3 = type_pointer(arena, pointer_type1); - Type *pointer_type4 = type_pointer(arena, pointer_type2); - assert(pointer_type3 != pointer_type1); - assert(pointer_type3 == pointer_type4); - - Type **types = 0; - array_push(types, type_array(arena, type_int, 32)); - Type *func_type1 = type_lambda(arena, types[0], types, array_len(types)); - Type *func_type2 = type_lambda(arena, types[0], types, array_len(types)); - assert(func_type1 == func_type2); - - Type **types2 = 0; - { - array_push(types2, type_array(arena, type_int, 32)); - array_push(types2, type_int); - } - array_push(types, type_int); - Type *func_type3 = type_lambda(arena, types[0], types, array_len(types)); - Type *func_type4 = type_lambda(arena, types[0], types2, array_len(types)); - assert(func_type1 != func_type3); - assert(func_type3 == func_type4); - - arena_end_scratch(); -}