diff --git a/ast.h b/ast.h index 175a582..c944148 100644 --- a/ast.h +++ b/ast.h @@ -1,5 +1,16 @@ #if 0 +OS_Memory:struct{ + data: void*; + commit: SizeU; + reserve: SizeU; +} + +Arena:struct{ + @using memory: OS_Memory; + len: U64; + alignment: U64; +} String:struct{ str: U8*; @@ -7,6 +18,8 @@ String:struct{ } Intern_String:typedef String; +@stringify +@prefix="TK_" Token_Kind:enum{ @str="End of stream" End, @str="*" Mul, @@ -73,13 +86,9 @@ Token_Kind:enum{ Keyword, } - Token:struct{ kind:Token_Kind; - union:{ - string:String; - struct:{str:U8*; len:U64;} - } + @using string:String; union:{ int_val:S64; error_val:String; @@ -90,17 +99,79 @@ Token:struct{ line_begin:U8*; } +Tokens:struct{ + @array tokens: Token*; + iter : S64; +} +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: 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, @@ -110,7 +181,8 @@ AST_Kind:enum{ AST_Node:struct{ kind: AST_Kind; - node: AST_Node[16]; + pos : Token*; + name: Intern_String; next: AST_Node*; next_scope: AST_Node*; @@ -129,6 +201,66 @@ AST_Node:struct{ } } +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; +} + +/* + +@register_tag(sllqueue) +@params(next=next,last=last,first=first) +function void +struct_type_lower_var_name_lower_push(struct_type *parent, var_type *child){ + if(parent->first == 0){ + - parent->first = parent->last = child; + } + else{ + - parent->last = parent->last->next = child; + } +} +*/ + #endif @@ -144,6 +276,7 @@ typedef enum AST_Kind{ AK_Struct, AK_Union, + AK_Identifier, AK_Note, AK_List, diff --git a/common.c b/common.c index 72c1691..cebe3d2 100644 --- a/common.c +++ b/common.c @@ -5,6 +5,12 @@ clamp_top_s64(S64 val, S64 max){ return val; } +function SizeU +clamp_top_sizeu(SizeU val, SizeU max){ + if(val>max)return max; + return val; +} + function SizeU get_align_offset(SizeU size, SizeU align){ SizeU mask = align - 1; @@ -55,3 +61,26 @@ string_compare(String a, String b){ } return true; } + +function U8 +char_to_lower(U8 c){ + if(c >= 'A' && c <= 'Z') + c += 32; + return c; +} + +function U8 +char_to_upper(U8 c){ + if(c >= 'a' && c <= 'z') + c -= 32; + return c; +} + +function String +string_to_lower(Arena *arena, String string){ + String result = arena_push_string_copy(arena, string); + for(S64 i = 0; i < string.len; i++){ + result.str[i] = char_to_lower(result.str[i]); + } + return result; +} diff --git a/lex.h b/lex.h index 8bc4d88..5d8796b 100644 --- a/lex.h +++ b/lex.h @@ -106,6 +106,7 @@ typedef struct Lex_Stream{ //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- + global String token_kind_string[] = { [TK_End] = lit("End of stream"), [TK_Error] = lit("Error"), @@ -170,3 +171,69 @@ global String token_kind_string[] = { [TK_Arrow] = lit("->"), [TK_ExprSizeof] = lit("sizeof"), }; + +global String Token_Kind_metadata[] = { + [TK_End] = lit("End of stream"), + [TK_Mul] = lit("*"), + [TK_Div] = lit("/"), + [TK_Add] = lit("+"), + [TK_Sub] = lit("-"), + [TK_Mod] = lit("%"), + [TK_BitAnd] = lit("&"), + [TK_BitOr] = lit("|"), + [TK_BitXor] = lit("^"), + [TK_Neg] = lit("~"), + [TK_Not] = lit("!"), + [TK_OpenParen] = lit("("), + [TK_CloseParen] = lit(" "), + [TK_OpenBrace] = lit("{"), + [TK_CloseBrace] = lit("}"), + [TK_OpenBracket] = lit("["), + [TK_CloseBracket] = lit("]"), + [TK_Comma] = lit(","), + [TK_Pound] = lit("#"), + [TK_Question] = lit("?"), + [TK_ThreeDots] = lit("..."), + [TK_Semicolon] = lit(";"), + [TK_Dot] = lit("."), + [TK_LesserThen] = lit("<"), + [TK_GreaterThen] = lit(">"), + [TK_Colon] = lit(":"), + [TK_Assign] = lit("="), + [TK_DivAssign] = lit("/="), + [TK_MulAssign] = lit("*="), + [TK_ModAssign] = lit("%="), + [TK_SubAssign] = lit("-="), + [TK_AddAssign] = lit("+="), + [TK_AndAssign] = lit("&="), + [TK_OrAssign] = lit("|="), + [TK_XorAssign] = lit("^="), + [TK_LeftShiftAssign] = lit("<<="), + [TK_RightShiftAssign] = lit(">>="), + [TK_DoubleColon] = lit("::"), + [TK_At] = lit("@"), + [TK_Decrement] = lit("--"), + [TK_Increment] = lit("++"), + [TK_PostDecrement] = lit("--"), + [TK_PostIncrement] = lit("++"), + [TK_LesserThenOrEqual] = lit("<="), + [TK_GreaterThenOrEqual] = lit(">="), + [TK_Equals] = lit("=="), + [TK_And] = lit("&&"), + [TK_Or] = lit("||"), + [TK_NotEquals] = lit("!="), + [TK_LeftShift] = lit("<<"), + [TK_RightShift] = lit(">>"), + [TK_Arrow] = lit("->"), + [TK_ExprSizeof] = lit("sizeof"), + [TK_DocComment] = lit("DocComment"), + [TK_Comment] = lit("Comment"), + [TK_Identifier] = lit("Identifier"), + [TK_StringLit] = lit("StringLit"), + [TK_U8Lit] = lit("U8Lit"), + [TK_Character] = lit("Character"), + [TK_Error] = lit("Error"), + [TK_Float] = lit("Float"), + [TK_Int] = lit("Int"), + [TK_Keyword] = lit("Keyword"), +}; diff --git a/main.c b/main.c index 3e57b66..b79492b 100644 --- a/main.c +++ b/main.c @@ -81,7 +81,7 @@ parser_test(){ String exprs[] = { lit("(4+2*53)"), - lit("((4+2)*53"), + lit("((4+2)*53)"), lit("++5"), lit("5--"), // @Todo(Krzosa): lit("-5"), @@ -95,18 +95,10 @@ parser_test(){ parser_lex_stream(&p, exprs[i], lit("File")); Expr *expr = parse_expr(&p); assert(expr); - expr_print(expr); - lex_print("\n"); + //expr_print(expr); + //lex_print("\n"); } - /* - String decls = - lit("@Test(a=\"thing\") @str=\"based\" Thing:enum{ Thing_1 = 1<<10, Thing_2 = 10 }" - "TTT:struct{ thing:U64; nested:struct{ thing:S64; }}" - "" - ); - */ - String decls = os_read_file(lit("ast.h")); parser_lex_stream(&p, decls, lit("File")); AST_Node *node = parse(&p); @@ -114,6 +106,32 @@ parser_test(){ assert(node->last_child); ast_print(node); + for(AST_Node *n = node->first_child; n; n=n->next){ + if(n->kind == AK_Enum){ + AST_Node *prefix = ast_find_note(n, lit("prefix")); + lex_print("global String %s_metadata[] = {\n", n->name.s.str); + for(AST_Node *member = n->first_child; member; member=member->next){ + lex_print("["); + if(prefix) expr_print(prefix->expr); + lex_print("%s] = ", member->name.s.str); + AST_Node *str = ast_find_note(member, lit("str")); + lex_print("lit(\""); + if(str){ + expr_print(str->expr); + } + else { + lex_print("%s", member->name.s.str); + } + lex_print("\")"); + lex_print(",\n"); + } + lex_print("};\n"); + + } + else if(n->kind == AK_Struct){ + gen_struct(n, (Intern_String){}); + } + } } function S32 @@ -123,6 +141,18 @@ os_main(){ lex_test(); parser_test(); + String_Map maps[] = { + {lit("cap"), lit("cap")}, + {lit("len"), lit("len")}, + {lit("data"), lit("tokens")}, + {lit("parent_type"), lit("Tokens")}, + {lit("parent_type_lower"), lit("tokens")}, + {lit("var_type_lower"), lit("token")}, + {lit("var_type"), lit("Token")}, + {lit("var_name"), lit("tokens")}, + }; + + /* String keywords[]={ lit("S64"), diff --git a/memory.c b/memory.c index ea521c3..7a08304 100644 --- a/memory.c +++ b/memory.c @@ -40,6 +40,23 @@ arena_push_size(Arena *a, SizeU size){ return result; } +function void +arena_pop_pos(Arena *arena, SizeU pos){ + pos = clamp_top_sizeu(pos, arena->len); + arena->len = pos; +} + +function Arena_Checkpoint +arena_checkpoint(Arena *arena){ + Arena_Checkpoint result = {arena, arena->len}; + return result; +} + +function void +arena_restore(Arena_Checkpoint checkpoint){ + arena_pop_pos(checkpoint.arena, checkpoint.pos); +} + function String arena_push_string_copy(Arena *arena, String string){ U8 *copy = arena_push_array(arena, U8, string.len+1); @@ -47,3 +64,28 @@ arena_push_string_copy(Arena *arena, String string){ copy[string.len] = 0; return (String){copy, string.len}; } + +function String +string_fmtv(Arena *arena, const char *str, va_list args1) { + va_list args2; + va_copy(args2, args1); + U64 len = vsnprintf(0, 0, str, args2); + va_end(args2); + + char *result = (char *)arena_push_size(arena, len + 1); + vsnprintf(result, len + 1, str, args1); + if (arena->len > 0) + arena->len -= 1; + + return (String){(U8 *)result, len}; +} + +function String +string_fmt(Arena *arena, const char *str, ...) { + va_list args1; + va_start(args1, str); + String result = string_fmtv(arena, str, args1); + va_end(args1); + return result; +} + diff --git a/memory.h b/memory.h index 182a221..a163284 100644 --- a/memory.h +++ b/memory.h @@ -5,6 +5,11 @@ typedef struct Arena{ U64 alignment; }Arena; +typedef struct Arena_Checkpoint{ + Arena *arena; + SizeU pos; +} Arena_Checkpoint; + function B32 string_compare(String a, String b); function void *arena_push_size(Arena *a, SizeU size); function String arena_push_string_copy(Arena *arena, String string); diff --git a/output.cc b/output.cc index 3e2f7d6..045926d 100644 --- a/output.cc +++ b/output.cc @@ -1,129 +1,166 @@ -(4+(2*53)) -Error: Expected token of kind: ), got instead token of kind: End of stream -((4+2)*53) -(++5) -(--5) -(-5) -(+5) -(()5) -((()5)+3) -((534>43)?435:42) -(((534>43)?435:42),234,(()42),Thing[10][2],Thing(1,2)) +typedef struct OS_Memory OS_Memory; +struct OS_Memory{ +void *data; +SizeU commit; +SizeU reserve; +}; + +typedef struct Arena Arena; +struct Arena{ +union{ +OS_Memory memory; +struct { +void *data; +SizeU commit; +SizeU reserve; +}; +} +U64 len; +U64 alignment; +}; + typedef struct String String; struct String{ U8 *str; S64 len; }; -typedef Intern_String; -enum Token_Kind{ - End, - Mul, - Div, - Add, - Sub, - Mod, - BitAnd, - BitOr, - BitXor, - Neg, - Not, - OpenParen, - CloseParen, - OpenBrace, - CloseBrace, - OpenBracket, - CloseBracket, - Comma, - Pound, - Question, - ThreeDots, - Semicolon, - Dot, - LesserThen, - GreaterThen, - Colon, - Assign, - DivAssign, - MulAssign, - ModAssign, - SubAssign, - AddAssign, - AndAssign, - OrAssign, - XorAssign, - LeftShiftAssign, - RightShiftAssign, - DoubleColon, - At, - Decrement, - Increment, - PostDecrement, - PostIncrement, - LesserThenOrEqual, - GreaterThenOrEqual, - Equals, - And, - Or, - NotEquals, - LeftShift, - RightShift, - Arrow, - ExprSizeof, - DocComment, - Comment, - Identifier, - StringLit, - U8Lit, - Character, - Error, - Float, - Int, - Keyword, -} +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; typedef struct Token Token; struct Token{ Token_Kind kind; -union { +union{ String string; struct { U8 *str; -U64 len; +S64 len; }; - -}; - +} union { S64 int_val; String error_val; -String intern_val; +Intern_String intern_val; }; - String file; S64 line; U8 *line_begin; }; -enum AST_Kind{ - BaseType, - Typedef, - Enum, - Struct, - Union, - Note, - List, - Pointer, - Array, - Function, - Variable, - EnumChild, -} +typedef struct Tokens Tokens; +struct Tokens{ +Token *tokens; +S64 len; +S64 cap; +S64 iter; +}; + +typedef struct Lex_Stream Lex_Stream; +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; + +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; typedef struct AST_Node AST_Node; struct AST_Node{ AST_Kind kind; -AST_Node node[16]; +Token *pos; +Intern_String name; AST_Node *next; AST_Node *next_scope; AST_Node *first_note; @@ -137,6 +174,218 @@ AST_Node *typedef_type; AST_Node *variable_type; AST_Node *func_return_type; }; - }; +typedef struct Parser_Error Parser_Error; +struct Parser_Error{ +Parser_Error *next; +String message; +Token *token; +}; + +typedef struct Scope Scope; +struct Scope{ +Scope *next; +AST_Node *first; +AST_Node *last; +}; + +typedef struct Parser Parser; +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 *first_default; +Parser_Error *last_default; + +Parser_Error *first_error; +Parser_Error *last_error; + +union{ +Tokens token_array; +struct { +Token *tokens; +S64 len; +S64 cap; +S64 iter; +}; +} +}; + +global String Token_Kind_metadata[] = { +[TK_End] = lit("End of stream"), +[TK_Mul] = lit("*"), +[TK_Div] = lit("/"), +[TK_Add] = lit("+"), +[TK_Sub] = lit("-"), +[TK_Mod] = lit("%"), +[TK_BitAnd] = lit("&"), +[TK_BitOr] = lit("|"), +[TK_BitXor] = lit("^"), +[TK_Neg] = lit("~"), +[TK_Not] = lit("!"), +[TK_OpenParen] = lit("("), +[TK_CloseParen] = lit(" "), +[TK_OpenBrace] = lit("{"), +[TK_CloseBrace] = lit("}"), +[TK_OpenBracket] = lit("["), +[TK_CloseBracket] = lit("]"), +[TK_Comma] = lit(","), +[TK_Pound] = lit("#"), +[TK_Question] = lit("?"), +[TK_ThreeDots] = lit("..."), +[TK_Semicolon] = lit(";"), +[TK_Dot] = lit("."), +[TK_LesserThen] = lit("<"), +[TK_GreaterThen] = lit(">"), +[TK_Colon] = lit(":"), +[TK_Assign] = lit("="), +[TK_DivAssign] = lit("/="), +[TK_MulAssign] = lit("*="), +[TK_ModAssign] = lit("%="), +[TK_SubAssign] = lit("-="), +[TK_AddAssign] = lit("+="), +[TK_AndAssign] = lit("&="), +[TK_OrAssign] = lit("|="), +[TK_XorAssign] = lit("^="), +[TK_LeftShiftAssign] = lit("<<="), +[TK_RightShiftAssign] = lit(">>="), +[TK_DoubleColon] = lit("::"), +[TK_At] = lit("@"), +[TK_Decrement] = lit("--"), +[TK_Increment] = lit("++"), +[TK_PostDecrement] = lit("--"), +[TK_PostIncrement] = lit("++"), +[TK_LesserThenOrEqual] = lit("<="), +[TK_GreaterThenOrEqual] = lit(">="), +[TK_Equals] = lit("=="), +[TK_And] = lit("&&"), +[TK_Or] = lit("||"), +[TK_NotEquals] = lit("!="), +[TK_LeftShift] = lit("<<"), +[TK_RightShift] = lit(">>"), +[TK_Arrow] = lit("->"), +[TK_ExprSizeof] = lit("sizeof"), +[TK_DocComment] = lit("DocComment"), +[TK_Comment] = lit("Comment"), +[TK_Identifier] = lit("Identifier"), +[TK_StringLit] = lit("StringLit"), +[TK_U8Lit] = lit("U8Lit"), +[TK_Character] = lit("Character"), +[TK_Error] = lit("Error"), +[TK_Float] = lit("Float"), +[TK_Int] = lit("Int"), +[TK_Keyword] = lit("Keyword"), +}; +function + Token*Tokens_array_push_empty(Tokens*a){ +if(a->cap==0){ +a->cap=1024; +a->tokens=malloc(sizeof(Token)*a->cap); +} +else if(a->len+1>a->cap){ +a->cap*=2; +a->tokens=realloc(a->tokens,sizeof(Token)*a->cap); +} +Token*result=a->tokens+a->len++; +memory_zero(result,sizeof(*result)); +return result; +} +global String Expr_Kind_metadata[] = { +[EK_None] = lit("None"), +[EK_Atom] = lit("Atom"), +[EK_Unary] = lit("Unary"), +[EK_Binary] = lit("Binary"), +[EK_Ternary] = lit("Ternary"), +[EK_Cast] = lit("Cast"), +[EK_List] = lit("List"), +[EK_Call] = lit("Call"), +[EK_Index] = lit("Index"), +}; +global String AST_Kind_metadata[] = { +[AK_None] = lit("None"), +[AK_BaseType] = lit("BaseType"), +[AK_Typedef] = lit("Typedef"), +[AK_Enum] = lit("Enum"), +[AK_Struct] = lit("Struct"), +[AK_Union] = lit("Union"), +[AK_Note] = lit("Note"), +[AK_List] = lit("List"), +[AK_Pointer] = lit("Pointer"), +[AK_Array] = lit("Array"), +[AK_Function] = lit("Function"), +[AK_Variable] = lit("Variable"), +[AK_EnumChild] = lit("EnumChild"), +}; +function + void parser_default_push(Parser*parent,Parser_Error*child){ +if(parent->first==0){ +parent->first=parent->last=child; +} +else{ +parent->last=parent->last->next=child; +} +} +function + Parser_Error*parser_default_pop_first(Parser*parent){ +if(parent->first==parent->last){ +Parser_Error*node=parent->first; +parent->first=parent->last=0; +return node; +} +else if(parent->first){ +Parser_Error*node=parent->first; +parent->first=parent->first->next; +} +return 0; +} + +function + void parser_error_push(Parser*parent,Parser_Error*child){ +if(parent->first_error==0){ +parent->first_error=parent->last_error=child; +} +else{ +parent->last_error=parent->last_error->next_error=child; +} +} +function + Parser_Error*parser_error_pop_first(Parser*parent){ +if(parent->first_error==parent->last_error){ +Parser_Error*node=parent->first_error; +parent->first_error=parent->last_error=0; +return node; +} +else if(parent->first_error){ +Parser_Error*node=parent->first_error; +parent->first_error=parent->first_error->next_error; +} +return 0; +} + +function + Token*Parser_array_push_empty(Parser*a){ +if(a->cap==0){ +a->cap=1024; +a->tokens=malloc(sizeof(Token)*a->cap); +} +else if(a->len+1>a->cap){ +a->cap*=2; +a->tokens=realloc(a->tokens,sizeof(Token)*a->cap); +} +Token*result=a->tokens+a->len++; +memory_zero(result,sizeof(*result)); +return result; +} diff --git a/print.c b/print.c index 65a25d0..540bf91 100644 --- a/print.c +++ b/print.c @@ -87,7 +87,7 @@ ast_get_basis_type(AST_Node *node){ switch(node->kind) { case AK_Struct: case AK_Union: case AK_Enum: case AK_BaseType:{return node;} break; case AK_Function:{return node;} break; - case AK_Typedef:{return node->typedef_type;} break; + case AK_Typedef:{return node;} break; case AK_Array: case AK_Pointer:{return ast_get_basis_type(node->pointer);} break; default: invalid_codepath; } @@ -149,6 +149,29 @@ ast_print_var(AST_Node *node){ } } +function AST_Node * +ast_find_note(AST_Node *node, String string){ + for(AST_Node *n = node->first_note; n; n=n->next){ + if(string_compare(n->name.s, string)){ + return n; + } + } + return 0; +} + +function String +ast_find_string(AST_Node *node, String string, String default_val){ + AST_Node *find = ast_find_note(node, string); + if(find){ + if(find->expr->kind == EK_Atom){ + return find->expr->token->string; + } + } + return default_val; +} + +global Arena todo_arena; + function void ast__print(AST_Node *node, S64 indent){ switch(node->kind){ @@ -166,12 +189,40 @@ ast__print(AST_Node *node, S64 indent){ if(indent == 0) lex_print("typedef %s %s %s;\n", type, node->name.s.str, node->name.s.str); lex_print("%s %s{\n", type, indent == 0 ? node->name.s.str:(U8 *)""); for(AST_Node *n = node->first_child; n; n=n->next){ - ast__print(n, indent+2); + AST_Node *using_note = ast_find_note(n, lit("using")); + AST_Node *array_note = ast_find_note(n, lit("array")); + AST_Node *sllqueue_note = ast_find_note(n, lit("sllqueue")); + if(using_note) { + assert(n->kind == AK_Variable); + lex_print("union{\n"); + ast__print(n, indent+2); + lex_print("\n"); + Intern_String name = n->variable_type->name; + n->variable_type->name = (Intern_String){0}; + assert(n->variable_type->kind == AK_Struct || n->variable_type->kind == AK_Union); + ast__print(n->variable_type, indent+2); + n->variable_type->name = name; + lex_print("\n}"); + } + else if(array_note){ + AST_Node *cap = ast_find_note(n, lit("cap")); + AST_Node *len = ast_find_note(n, lit("len")); + ast__print(n, indent+2); + lex_print("\nS64 len;\nS64 cap;"); + } + else if(sllqueue_note){ + lex_print("%s *first_%s;\n", n->variable_type->name.s.str, string_to_lower(&todo_arena, n->name.s).str); + lex_print("%s *last_%s;\n", n->variable_type->name.s.str, string_to_lower(&todo_arena, n->name.s).str); + } + else { + ast__print(n, indent+2); + } lex_print("\n"); } lex_print("}"); - lex_print("%s;\n", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)""); + lex_print("%s;", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)""); + if(indent == 0) lex_new_line(); } break; case AK_Variable:{ @@ -182,15 +233,20 @@ ast__print(AST_Node *node, S64 indent){ case AK_Typedef:{ lex_print("typedef "); - lex_print("%s;", node->name.s.str); + ast_print_var(node); + lex_print(";"); } break; case AK_Enum:{ print_indent(indent); - lex_print("enum %s{\n", node->name.s.str); + lex_print("typedef enum %s{\n", node->name.s.str); + AST_Node *prefix = ast_find_note(node, lit("prefix")); for(AST_Node *n = node->first_child; n; n=n->next){ print_indent(indent+2); + if(prefix){ + expr_print(prefix->expr); + } lex_print("%s", n->name.s.str); if(n->expr){ lex_print(" = "); @@ -200,7 +256,7 @@ ast__print(AST_Node *node, S64 indent){ } print_indent(indent); - lex_print("}\n"); + lex_print("}%s;\n", node->name.s.str); } break; default: invalid_codepath; @@ -211,3 +267,149 @@ function void ast_print(AST_Node *node){ ast__print(node, 0); } + +function B32 +intern_is_empty(Intern_String string){ + if(string.s.str == 0) + return true; + return false; +} + +typedef struct String_Map{ + String replace; + String with; +}String_Map; + +function B32 +token_is_number(Token *token){ + B32 result = token->kind == TK_Int; + return result; +} + +function void +print_string_replaced(String string, String_Map *maps, SizeU count){ + Tokens tokens = lex_stream(string, lit("Replace")); + for(S64 i = 0; i < tokens.len; i++){ + Token *t = tokens.tokens + i; + if(t->kind == TK_At) continue; + for(String_Map *map = maps; map != maps+count; map++){ + if(string_compare(map->replace, t->string)){ + t->string = map->with; + } + } + + lex_print("%.*s", (S32)t->string.len, t->string.str); + if(t->kind == TK_Keyword) lex_print(" "); + if(t->kind == TK_Identifier && + (t[1].kind== TK_Identifier || token_is_number(t+1))) lex_print(" "); + if(t->kind == TK_OpenBrace) lex_print("\n"); + if(t->kind == TK_CloseBrace) lex_print("\n"); + if(t->kind == TK_Semicolon) lex_print("\n"); + } + free(tokens.tokens); + +} + +function void +gen_struct(AST_Node *n, Intern_String shadow_type_name){ + for(AST_Node *member = n->first_child; member; member=member->next){ + AST_Node *using_note = ast_find_note(member, lit("using")); + AST_Node *array_note = ast_find_note(member, lit("array")); + AST_Node *sllqueue_note = ast_find_note(member, lit("sllqueue")); + if(using_note){ + gen_struct(member->variable_type, n->name); + } + if(array_note){ + AST_Node *array_type = ast_get_basis_type(member->variable_type); + + Intern_String type_name = n->name; + if(!intern_is_empty(shadow_type_name)) + type_name = shadow_type_name; + + + String_Map maps[] = { + {lit("function"), lit("function\n")}, + {lit("base_type"), type_name.s}, + {lit("base_type_lower"), string_to_lower(&todo_arena, type_name.s)}, + {lit("var_type"), array_type->name.s}, + {lit("var_type_lower"), string_to_lower(&todo_arena, array_type->name.s)}, + {lit("var_name"), member->name.s}, + {lit("var_name_lower"), string_to_lower(&todo_arena, member->name.s)}, + {lit("len"), ast_find_string(array_note, lit("len"), lit("len"))}, + {lit("cap"), ast_find_string(array_note, lit("cap"), lit("cap"))}, + {lit("data"), ast_find_string(array_note, lit("data"), lit("data"))}, + }; + + + String a + = lit("function var_type *base_type@_array_push_empty(base_type *a){" + "if(a->cap == 0){\n" + " a->cap = 1024;\n" + " a->tokens = malloc(sizeof(var_type)*a->cap);\n" + "}\n" + "else if(a->len+1 > a->cap){\n" + " a->cap *= 2;\n" + " a->tokens = realloc(a->tokens, sizeof(var_type)*a->cap);\n" + "}\n" + + "var_type *result = a->tokens + a->len++;\n" + "memory_zero(result, sizeof(*result));\n" + "return result;}"); + print_string_replaced(a, maps, buff_cap(maps)); + } + if(sllqueue_note){ + String default_first = lit("first"); + String default_last = lit("last"); + String default_next = lit("next"); + if(!string_compare(member->name.s, lit("default"))){ + default_first = string_fmt(&todo_arena, "first_%s", member->name.s.str); + default_last = string_fmt(&todo_arena, "last_%s", member->name.s.str); + default_next = string_fmt(&todo_arena, "next_%s", member->name.s.str); + } + + String_Map maps[] = { + {lit("function"), lit("function\n")}, + {lit("base_type"), n->name.s}, + {lit("base_type_lower"), string_to_lower(&todo_arena, n->name.s)}, + {lit("var_type"), member->variable_type->name.s}, + {lit("var_type_lower"), string_to_lower(&todo_arena, member->variable_type->name.s)}, + {lit("var_name"), member->name.s}, + {lit("var_name_lower"), string_to_lower(&todo_arena, member->name.s)}, + {lit("next"), ast_find_string(sllqueue_note, lit("next"), default_next)}, + {lit("first"), ast_find_string(sllqueue_note, lit("first"), default_first)}, + {lit("last"), ast_find_string(sllqueue_note, lit("last"), default_last)}, + }; + + String string = + lit( + "function void " + "base_type_lower@_@var_name_lower@_push(base_type *parent, var_type *child){" + "if(parent->first == 0){" + "parent->first = parent->last = child;" + "}" + "else{" + "parent->last = parent->last->next = child;" + "}" + "}" + + "function var_type * " + "base_type_lower@_@var_name_lower@_pop_first(base_type *parent){" + " if(parent->first == parent->last){" + " var_type *node = parent->first;" + " parent->first = parent->last = 0;" + " return node;" + " }" + " else if(parent->first){" + " var_type *node = parent->first;" + " parent->first = parent->first->next;" + " }" + "return 0;" + "}" + + + ); + print_string_replaced(string, maps, buff_cap(maps)); + lex_print("\n"); + } + } +} \ No newline at end of file