diff --git a/decl.c b/decl.c index c8eea08..b8814cc 100644 --- a/decl.c +++ b/decl.c @@ -2,7 +2,6 @@ function Decl * decl_new(Parser *p, Decl_Kind kind, Token *token, Intern_String name){ Decl *result = arena_push_struct(&p->main_arena, Decl); - memory_zero(result, sizeof(Decl)); result->token = token; result->kind = kind; @@ -13,12 +12,33 @@ decl_new(Parser *p, Decl_Kind kind, Token *token, Intern_String name){ function Decl_Enum_Child * decl_enum_child(Parser *p, Token *token, Expr *expr){ Decl_Enum_Child *result = arena_push_struct(&p->main_arena, Decl_Enum_Child); - memory_zero(result, sizeof(Decl_Enum_Child)); result->expr = expr; result->token = token; return result; } +function Decl * +decl_variable(Parser *p, Token *token, Type *type, Expr *expr){ + Decl *result = decl_new(p, DK_Variable, token, token->intern_val); + result->var_val.expr = expr; + result->var_val.type = type; + return result; +} + +function Decl * +decl_function(Parser *p, Token *token, Type *return_type){ + Decl *result = decl_new(p, DK_Function, token, token->intern_val); + result->func_val.return_type = return_type; + return result; +} + +function Decl * +decl_type(Parser *p, Token *token, Type *type, Intern_String name){ + Decl *result = decl_new(p, DK_Typedef, token, name); + result->typedef_val.type = type; + return result; +} + function Decl * decl_enum(Parser *p, Token *token, Intern_String name){ Decl *result = decl_new(p, DK_Enum, token, name); diff --git a/decl.h b/decl.h index 0096c74..1fa40b9 100644 --- a/decl.h +++ b/decl.h @@ -61,3 +61,68 @@ struct Decl{ }; }; +//----------------------------------------------------------------------------- +// Idea +//----------------------------------------------------------------------------- +typedef struct AST_Node AST_Node; +typedef enum AST_Kind{ + AK_None, + AK_Undefined, + AK_BaseType, + AK_Typedef, + AK_Pointer, + AK_Struct, + AK_Union, + AK_Array, + AK_Function, + AK_Variable, + AK_EnumChild, +}AST_Kind; + +struct AST_Node{ + AST_Kind kind; + Intern_String name; + Expr *expr; + Token *pos; + + AST_Node *next; + AST_Node *first_note; + AST_Node *last_note; + union{ + AST_Node *pointer; + struct{ + SizeU size; + }base_type_val; + struct{ + AST_Node *type; + }typedef_val; + struct{ + AST_Node *return_type; + AST_Node *first; + AST_Node *last; + }func_val; + struct{ + AST_Node *first; + AST_Node *last; + }aggregate; + struct{ + AST_Node *first; + AST_Node *last; + }enum_val; + }; +}; + +// Then I can yoink the entire idea of a symbol +// cause AST_Node is THE symbol +typedef struct Scope{ + Scope *next; + AST_Node *first; + AST_Node *last; +}Scope; + +{ + Scope *first; + Scope *last; +} + +scope_pop(Parser *p) diff --git a/expr.c b/expr.c index 003fea5..9ded132 100644 --- a/expr.c +++ b/expr.c @@ -2,7 +2,6 @@ function Expr * expr_new(Parser *p, Expr_Kind kind, Token *token){ Expr *expr = arena_push_struct(&p->main_arena, Expr); - memory_zero(expr, sizeof(Expr)); expr->kind = kind; expr->token = token; return expr; diff --git a/main.c b/main.c index a766d64..549feb5 100644 --- a/main.c +++ b/main.c @@ -11,6 +11,10 @@ #include "expr.h" #include "decl.h" +global FILE *global_output_file; +#define lex_print(...) fprintf(global_output_file, __VA_ARGS__) +#define lex_new_line() lex_print("\n") + #include "common.c" #include "memory.c" #include "parser.c" @@ -99,6 +103,9 @@ parser_test(){ String decls[] = { lit("enum Thing{ Thing_1, Thing_2 = 2}"), + lit("global S64 *variable[10] = 10"), + lit("global S64 (*variable)(S64 thing) = 10"), + lit("struct Thing{ S64 a; U64 *b; union A{ S64 thing; }; }"), }; for(S64 i = 0; i < buff_cap(decls); i++){ parser_lex_stream(&p, decls[i], lit("File")); diff --git a/memory.c b/memory.c index 2718c6c..f6d4a05 100644 --- a/memory.c +++ b/memory.c @@ -35,6 +35,8 @@ arena_push_size(Arena *a, SizeU size){ a->len = align_up(a->len, a->alignment); void *result = (U8*)a->memory.data + a->len; a->len += size; + + memory_zero(result, size); return result; } diff --git a/parse_decl.c b/parse_decl.c index 29307f6..ca84f06 100644 --- a/parse_decl.c +++ b/parse_decl.c @@ -1,3 +1,10 @@ +function Decl *parse_decl_variable(Parser *p); + +function B32 +intern_empty(Intern_String a){ + B32 result = (a.s.str == 0); + return result; +} function Decl * parse_decl_enum(Parser *p){ @@ -17,6 +24,7 @@ parse_decl_enum(Parser *p){ expr = parse_expr(p); } Decl_Enum_Child *child = decl_enum_child(p, token, expr); + const_val_insert(p, token, type_s64, token->intern_val, expr); decl_enum_push(result, child); } else break; @@ -32,29 +40,179 @@ parse_decl_enum(Parser *p){ } } + if(!intern_empty(name)){ + Type *type = type_enum(p, result); + type_insert(p, type, name); + } + + return result; +} + +function void +parse_decl_variable_right(Parser *p, Type **type, Token **name){ + while(token_match(p, TK_Mul)){ + *type = type_pointer(p, *type); + }; + *name = token_expect(p, TK_Identifier); + while(token_match(p, TK_OpenBracket)){ + Expr *expr = parse_expr(p); + *type = type_array(p, *type, expr); + token_expect(p, TK_CloseBracket); + } +} + +function void +parse_argument_list(Parser *p, Decl *func){ + if(!token_is(p, TK_CloseParen)){ + do{ + Decl *var = parse_decl_variable(p); + decl_function_push(func, var); + }while(token_match(p, TK_Comma)); + } +} + +function Decl * +parse_decl_variable(Parser *p){ + Decl *result = 0; + Token *name = 0; + Type *type = 0; + Token *token = token_get(p); + if(token_match(p, TK_Identifier) || + token_match(p, TK_Keyword)){ + type = type_get(p, token->intern_val); + if(token_match(p, TK_OpenParen)){ + token_expect(p, TK_Mul); + if((name = token_expect(p, TK_Identifier))){ + token_expect(p, TK_CloseParen); + token_expect(p, TK_OpenParen); + Decl *function_p = decl_function(p, name, type); + parse_argument_list(p, function_p); + token_expect(p, TK_CloseParen); + type = type_function_pointer(p, function_p); + } + } + else { + parse_decl_variable_right(p, &type, &name); + } + } + else{ + parser_push_error(p, token, "Expected type when parsing global variable"); + } + + Expr *expr = 0; + if(token_match(p, TK_Assign)){ + expr = parse_expr(p); + } + + if(name){ + result = decl_variable(p, name, type, expr); + } + + return result; +} + +function Decl * +parse_decl_and_register_variable(Parser *p){ + Decl *result = parse_decl_variable(p); + if(result){ + variable_insert(p, result); + } + return result; +} + +function Decl * +parse_struct(Parser *p, Decl_Kind kind){ + Token *token = token_get(p); + Token *name = token_match(p, TK_Identifier); + Decl *result = decl_struct(p, token, name->intern_val); + result->kind = kind; + + if(token_expect(p, TK_OpenBrace)){ + do{ + if(token_match_keyword(p, keyword_struct)){ + Decl *val = parse_struct(p, DK_Struct); + decl_aggregate_push(result, val); + } + else if(token_match_keyword(p, keyword_union)){ + Decl *val = parse_struct(p, DK_Union); + decl_aggregate_push(result, val); + } + else if(token_is(p, TK_Keyword) || token_is(p, TK_Identifier)){ + Decl *val = parse_decl_variable(p); + decl_aggregate_push(result, val); + } + else if(token_is(p, TK_CloseBrace)){ + break; + } + else { + parser_push_error(p, token_get(p), "Failed to parse struct, unexpected token"); + break; + } + }while(token_match(p, TK_Semicolon)); + + token_expect(p, TK_CloseBrace); + } + + if(name){ + Type *type = type_struct(p, result); + type_insert(p, type, name->intern_val); + } + + return result; +} + +function Decl * +parse_decl_typedef(Parser *p){ + Decl *result = decl_type(p, token_get(p), 0, (Intern_String){}); + if(token_match_keyword(p, keyword_enum)){ + Decl *e = parse_decl_enum(p); + result->typedef_val.type = type_enum(p, e); + } + else if(token_match_keyword(p, keyword_union)){ + Decl *e = parse_struct(p, DK_Union); + result->typedef_val.type = type_struct(p, e); + } + else if(token_match_keyword(p, keyword_struct)){ + Decl *e = parse_struct(p, DK_Struct); + result->typedef_val.type = type_struct(p, e); + } + else if(token_is(p, TK_Keyword) || token_is(p, TK_Identifier)){ + Token *token = token_next(p); + result->typedef_val.type = type_get(p, token->intern_val); + } + else { + parser_push_error(p, token_get(p), "Failed to parse typedef, unexpected token"); + } + + Token *name = token_expect(p, TK_Identifier); + if(name){ + result->name = name->intern_val; + type_insert(p, type_typedef(p, result), result->name); + } + return result; } function Decl * parse_decl_global(Parser *p){ Decl *result = 0; - if(token_match_keyword(p, keyword_enum)){ + if(token_match_keyword(p, keyword_typedef)){ + result = parse_decl_typedef(p); + } + else if(token_match_keyword(p, keyword_enum)){ result = parse_decl_enum(p); - } - else if(token_match_keyword(p, keyword_typedef)){ - } else if(token_match_keyword(p, keyword_union)){ - + result = parse_struct(p, DK_Union); } else if(token_match_keyword(p, keyword_struct)){ - + result = parse_struct(p, DK_Struct); } else if(token_match_keyword(p, keyword_global)){ - + result = parse_decl_variable(p); } else if(token_match_keyword(p, keyword_function)){ } return result; -} \ No newline at end of file +} diff --git a/parse_expr.c b/parse_expr.c index 842d964..4fb649a 100644 --- a/parse_expr.c +++ b/parse_expr.c @@ -93,7 +93,7 @@ Expr* parse_unary_expr(Parser* p) { else if (token_is(p, TK_OpenParen)) { // cast requires lookahead Token *token = token_peek(p, 1); if (token->kind == TK_Keyword || token->kind == TK_Identifier) { - Type *type = type_get(p, token); + Type *type = type_get(p, token->intern_val); if(type != type_undefined){ token_next(p); token_next(p); diff --git a/parser.c b/parser.c index c947962..1540476 100644 --- a/parser.c +++ b/parser.c @@ -15,11 +15,9 @@ function void parser_init(Parser *p){ p->interns_count = 4096; p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count); - memory_zero(p->interns, sizeof(Intern_String)*p->interns_count); p->symbols_count = 4096; p->symbols = arena_push_array(&p->intern_table_arena, Intern_String, p->symbols_count); - memory_zero(p->symbols, sizeof(Intern_String)*p->symbols_count); keyword_s64 = intern_string(p, lit("S64")); keyword_u64 = intern_string(p, lit("U64")); @@ -50,6 +48,7 @@ intern_is_keyword(Parser *p, Intern_String intern){ function void parser_push_error(Parser *p, Token *token, char *str, ...){ + String string; { va_list args1, args2; @@ -63,6 +62,7 @@ parser_push_error(Parser *p, Token *token, char *str, ...){ va_end(args1); } + lex_print("Error: %s\n", string.str);// @Todo(Krzosa): Parser_Error *error = arena_push_struct(&p->main_arena, Parser_Error); error->message = string; error->next = 0; @@ -112,6 +112,8 @@ intern_string(Parser *p, String string){ Intern_String *intern = p->interns + index.iter; if(intern->s.str == 0){ result.s = arena_push_string_copy(&p->main_arena, string); + p->interns_in_bytes += string.len; + p->interns_inserted += 1; *intern = result; break; } @@ -141,26 +143,29 @@ intern_tokens(Parser *p){ } } -function void -symbol_insert(Parser *p, Symbol symbol){ - String string = symbol.string.s; +function Symbol * +symbol_get_slot(Parser *p, Intern_String intern){ + String string = intern.s; Table_Index index = table_index_from_string(string, p->symbols_count); for(;;){ Symbol *slot = p->symbols + index.iter; if(slot->string.s.str == 0){ - *slot = symbol; - break; + slot->string = intern; + p->symbols_inserted++; + return slot; } else if(slot->string.s.str == string.str){ - invalid_codepath; - break; + return slot; } if (table_index_advance(&index)) break; } + + parser_push_error(p, token_get(p), "Failed to find a spot for symbol"); + return 0; } function Symbol * @@ -179,31 +184,63 @@ symbol_get(Parser *p, Intern_String string){ return 0; } +function B32 +symbol_require_empty(Parser *p, Symbol *symbol){ + assert(symbol); + B32 result = symbol->kind == SK_None; + if(!result){ + // @Todo(Krzosa): Should send symbol name not token + parser_push_error(p, token_get(p), "This symbol name is already registered"); + } + return result; +} + +function void +const_val_insert(Parser *p, Token *token, Type *type, Intern_String string, Expr *expr){ + Symbol *symbol = symbol_get_slot(p, string); + if(symbol_require_empty(p, symbol)){ + symbol->kind = SK_Const; + symbol->token = token; + symbol->const_val.type = type; + symbol->const_val.expr = expr; + } +} + +function void +variable_insert(Parser *p, Decl *decl){ + Symbol *symbol = symbol_get_slot(p, decl->name); + if(symbol_require_empty(p, symbol)){ + symbol->kind = SK_Decl; + symbol->decl = decl; + symbol->string = decl->name; + symbol->token = decl->token; + } +} + function void type_insert(Parser *p, Type *type, Intern_String string){ - Symbol symbol = {.kind=SK_Type, .string=string, .type=type}; - symbol_insert(p, symbol); + Symbol *symbol = symbol_get_slot(p, string); + if(symbol_require_empty(p, symbol)){ + symbol->kind = SK_Type; + symbol->type = type; + symbol->string = string; + } } function Type * -type_get(Parser *p, Token *token){ +type_get(Parser *p, Intern_String string){ Type *result = 0; - if(token->kind == TK_Identifier || token->kind == TK_Keyword){ - Symbol *symbol = symbol_get(p, token->intern_val); - if(symbol){ - if(symbol->kind == SK_Type){ - result = symbol->type; - } - else { - parser_push_error(p, token, "Symbol is not a type"); - } + Symbol *symbol = symbol_get(p, string); + if(symbol){ + if(symbol->kind == SK_Type){ + result = symbol->type; } - else{ - parser_push_error(p, token, "Undefined type"); + else { + parser_push_error(p, token_get(p), "Symbol is not a type"); } } - else { - parser_push_error(p, token, "Trying to lookup a type with token of wrong kind"); + else{ + parser_push_error(p, token_get(p), "Undefined type"); } if(!result){ diff --git a/parser.h b/parser.h index 6490fe0..83eacc8 100644 --- a/parser.h +++ b/parser.h @@ -1,17 +1,27 @@ #pragma once typedef struct Type Type; +typedef struct Expr Expr; +typedef struct Decl Decl; typedef struct Parser_Error Parser_Error; typedef enum Symbol_Kind{ SK_None, SK_Type, + SK_Const, + SK_Decl, }Symbol_Kind; typedef struct Symbol{ Symbol_Kind kind; Intern_String string; + Token *token; struct{ Type *type; + struct{ + Type *type; + Expr *expr; + } const_val; + Decl *decl; }; }Symbol; @@ -26,9 +36,12 @@ typedef struct Parser{ Arena intern_table_arena; Arena symbol_table_arena; + S64 symbols_inserted; Symbol *symbols; S64 symbols_count; + S64 interns_in_bytes; + S64 interns_inserted; Intern_String *interns; S64 interns_count; @@ -43,4 +56,4 @@ typedef struct Parser{ function Intern_String intern_string(Parser *p, String string); function void type_insert(Parser *p, Type *type, Intern_String string); - +function Token *token_get(Parser *p); diff --git a/print.c b/print.c index e251952..79a593d 100644 --- a/print.c +++ b/print.c @@ -1,8 +1,4 @@ -global FILE *global_output_file; -#define lex_print(...) fprintf(global_output_file, __VA_ARGS__) -#define lex_new_line() lex_print("\n") - function void tokens_print(Tokens tokens){ lex_print("\n== Token count = %d\n", (S32)tokens.len); @@ -30,6 +26,14 @@ type_print(Type *type){ type_print(type->pointer); lex_print("*"); } break; + case TK_Function:{ + type_print(type->decl->func_val.return_type); + lex_print("("); + for(Decl *n = type->decl->func_val.first; n; n=n->next){ + token_print(n->token); // @Todo(Krzosa): + } + lex_print(")"); + } break; case TK_Array:{ type_print(type->array.pointer); lex_print("["); @@ -110,10 +114,29 @@ expr_print(Expr *expr){ } } - function void decl_print(Decl *decl){ switch(decl->kind) { + + case DK_Union: lex_print("union"); + case DK_Struct:{ + lex_print("struct %s{\n", decl->name.s.str); + for(Decl *n = decl->aggregate_val.first; n; n=n->next){ + decl_print(n); + lex_print(";\n"); + } + lex_print("}\n"); + } break; + + case DK_Variable:{ + type_print(decl->var_val.type); + lex_print(" %s", decl->name.s.str); + if(decl->var_val.expr){ + lex_print(" = "); + expr_print(decl->var_val.expr); + } + } break; + case DK_Enum: { lex_print("enum %s{\n", decl->name.s.str); for(Decl_Enum_Child *n = decl->enum_val.first; n; n=n->next){ diff --git a/type.c b/type.c index 05fb6d8..dd7c64f 100644 --- a/type.c +++ b/type.c @@ -2,8 +2,6 @@ function Type * type_new(Parser *p, Type_Kind kind){ Type *result = arena_push_struct(&p->main_arena, Type); - memory_zero(result, sizeof(Type)); - result->kind = kind; return result; } @@ -22,4 +20,40 @@ type_array(Parser *p, Type *base, Expr *index){ result->array.pointer = base; result->array.size = index; return result; +} + +function Type * +type_enum(Parser *p, Decl *enum_val){ + Type *result = type_new(p, TK_Enum); + result->decl = enum_val; + return result; +} + +function Type * +type_struct(Parser *p, Decl *struct_val){ + Type *result = type_new(p, TK_Struct); + result->decl = struct_val; + return result; +} + +function Type * +type_union(Parser *p, Decl *union_val){ + Type *result = type_new(p, TK_Union); + result->decl = union_val; + return result; +} + +function Type * +type_function_pointer(Parser *p, Decl *func_val){ + Type *result = type_new(p, TK_Function); + result->decl = func_val; + result = type_pointer(p, result); + return result; +} + +function Type * +type_typedef(Parser *p, Decl *typedef_val){ + Type *result = type_new(p, TK_Typedef); + result->decl = typedef_val; + return result; } \ No newline at end of file diff --git a/type.h b/type.h index 68142ee..3b123b8 100644 --- a/type.h +++ b/type.h @@ -1,6 +1,7 @@ #pragma once typedef struct Type Type; typedef struct Expr Expr; +typedef struct Decl Decl; typedef enum Type_Kind{ TK_None, @@ -10,8 +11,10 @@ typedef enum Type_Kind{ TK_SizeU, TK_Undefined, + TK_Typedef, TK_Function, TK_Pointer, + TK_Enum, TK_Array, TK_Struct, TK_Union, @@ -22,6 +25,7 @@ struct Type{ SizeU size; union{ Type *pointer; + Decl *decl; struct{ Type *pointer; Expr *size;