function void tokens_print(Tokens tokens){ lex_print("\n== Token count = %d\n", (S32)tokens.len); for(Token *t = tokens.tokens; t != tokens.tokens + tokens.len; t++){ lex_print("%s \"%.*s\"\n", token_kind_string[t->kind].str, (S32)t->len, t->str); } } function void token_print(Token *token){ lex_print("%.*s", (S32)token->len, token->str); } function void expr_print(Expr *expr){ switch(expr->kind) { case EK_Atom: { token_print(expr->token); } break; case EK_Binary:{ lex_print("("); expr_print(expr->binary.left); token_print(expr->token); expr_print(expr->binary.right); lex_print(")"); } break; case EK_Unary:{ lex_print("("); token_print(expr->token); expr_print(expr->unary.expr); lex_print(")"); } break; case EK_Ternary:{ lex_print("("); expr_print(expr->ternary.cond); lex_print("?"); expr_print(expr->ternary.on_true); lex_print(":"); expr_print(expr->ternary.on_false); lex_print(")"); } break; case EK_List:{ lex_print("("); for(Expr *n = expr->list.first; n; n=n->next){ expr_print(n); if(n!=expr->list.last) lex_print(","); } lex_print(")"); }break; case EK_Cast:{ lex_print("("); lex_print("("); //type_print(expr->cast.type); lex_print(")"); expr_print(expr->cast.expr); lex_print(")"); } break; case EK_Index:{ expr_print(expr->index.atom); lex_print("["); expr_print(expr->index.index); lex_print("]"); }break; case EK_Call:{ expr_print(expr->call.atom); expr_print(expr->call.list); }break; default: {invalid_codepath;} break; } } function void print_indent(S64 indent){ for(S64 i = 0; i < indent; i++){ lex_print(" "); } } function AST_Node * 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;} break; case AK_Array: case AK_Pointer:{return ast_get_basis_type(node->pointer);} break; default: invalid_codepath; } return 0; } function void ast_print_pointers(AST_Node *node){ if(node->kind == AK_Pointer){ lex_print("*"); ast_print_pointers(node->pointer); } else if(node->kind == AK_Array){ ast_print_pointers(node->pointer); } } function void ast_print_arrays(AST_Node *node){ if(node->kind == AK_Pointer){ ast_print_arrays(node->pointer); } else if(node->kind == AK_Array){ lex_print("["); expr_print(node->expr); lex_print("]"); ast_print_arrays(node->pointer); } } function void ast_print_var(AST_Node *node); function void ast_print_func_params(AST_Node *node){ for(AST_Node *n = node->first_child; n; n=n->next){ ast_print_var(n); if(n != node->last_child) lex_print(", "); } } function void ast_print_var(AST_Node *node){ AST_Node *basis_type = ast_get_basis_type(node->variable_type); if(basis_type->kind == AK_Function){ lex_print("%s (*%s)(", basis_type->func_return_type->name.s.str, node->name.s.str); ast_print_func_params(basis_type); lex_print(")"); } else{ lex_print("%s ", basis_type->name.s.str); ast_print_pointers(node->variable_type); lex_print("%s", node->name.s.str); ast_print_arrays(node->variable_type); } if(node->expr){ lex_print(" = "); expr_print(node->expr); } } 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){ case AK_List:{ for(AST_Node *n = node->first_child; n; n=n->next){ ast__print(n, indent); lex_print("\n"); } } break; case AK_Union: case AK_Struct:{ const char *type = node->kind == AK_Struct ? "struct":"union"; 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_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;", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)""); if(indent == 0) lex_new_line(); } break; case AK_Variable:{ if(indent == 0) lex_print("global "); ast_print_var(node); lex_print(";"); } break; case AK_Typedef:{ lex_print("typedef "); ast_print_var(node); lex_print(";"); } break; case AK_Enum:{ print_indent(indent); 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(" = "); expr_print(n->expr); } lex_print(",\n"); } print_indent(indent); lex_print("}%s;\n", node->name.s.str); } break; default: invalid_codepath; } } 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"); } } }