diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/codegen.c | 26 | ||||
| -rw-r--r-- | src/codegen/codegen.h | 4 | ||||
| -rw-r--r-- | src/codegen/codegen_decl.c | 98 | ||||
| -rw-r--r-- | src/codegen/codegen_main.c | 11 | ||||
| -rw-r--r-- | src/codegen/codegen_utils.c | 19 |
5 files changed, 95 insertions, 63 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index abffe84..1592806 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -1,10 +1,10 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> #include "codegen.h" #include "zprep.h" +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include "../plugins/plugin_manager.h" #include "ast.h" @@ -436,7 +436,9 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) case NODE_LAMBDA: if (node->lambda.num_captures > 0) { - fprintf(out, "({ struct Lambda_%d_Ctx *ctx = malloc(sizeof(struct Lambda_%d_Ctx));\n", + fprintf(out, + "({ struct Lambda_%d_Ctx *ctx = malloc(sizeof(struct " + "Lambda_%d_Ctx));\n", node->lambda.lambda_id, node->lambda.lambda_id); for (int i = 0; i < node->lambda.num_captures; i++) { @@ -818,7 +820,9 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) if (is_slice_struct) { - fprintf(out, "(Slice_%s){ .data = _arr.data + _start, .len = _len, .cap = _len }; })", + fprintf(out, + "(Slice_%s){ .data = _arr.data + _start, .len = _len, .cap = " + "_len }; })", tname); } else @@ -863,7 +867,8 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) fprintf(out, " _try = "); codegen_expression(ctx, node->try_stmt.expr, out); fprintf(out, - "; if (_try.tag == %s_Err_Tag) return (%s_Err(_try.data.Err)); _try.data.Ok; })", + "; if (_try.tag == %s_Err_Tag) return (%s_Err(_try.data.Err)); " + "_try.data.Ok; })", type_name, type_name); break; } @@ -1901,7 +1906,8 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) emit_auto_type(ctx, node->repl_print.expr, node->token, out); fprintf(out, " _zval = ("); codegen_expression(ctx, node->repl_print.expr, out); - fprintf(out, "); fprintf(stdout, _z_str(_zval), _zval); fprintf(stdout, \"\\n\"); }\n"); + fprintf(out, "); fprintf(stdout, _z_str(_zval), _zval); fprintf(stdout, " + "\"\\n\"); }\n"); break; } case NODE_AWAIT: @@ -1922,8 +1928,8 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) ret_type = node->resolved_type; } - // Fallback: If type is still Async/void* (likely from Future type, not Result type), try to - // infer + // Fallback: If type is still Async/void* (likely from Future type, not + // Result type), try to infer if (strcmp(ret_type, "Async") == 0 || strcmp(ret_type, "void*") == 0) { char *inf = infer_type(ctx, node); diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h index a7f3df3..d489fb3 100644 --- a/src/codegen/codegen.h +++ b/src/codegen/codegen.h @@ -2,10 +2,10 @@ #ifndef CODEGEN_H #define CODEGEN_H -#include <stdio.h> -#include "../zprep.h" #include "../ast/ast.h" #include "../parser/parser.h" +#include "../zprep.h" +#include <stdio.h> // Main codegen entry points. void codegen_node(ParserContext *ctx, ASTNode *node, FILE *out); diff --git a/src/codegen/codegen_decl.c b/src/codegen/codegen_decl.c index 8c8af97..b009a64 100644 --- a/src/codegen/codegen_decl.c +++ b/src/codegen/codegen_decl.c @@ -1,11 +1,11 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include "codegen.h" -#include "../zprep.h" #include "../ast/ast.h" #include "../parser/parser.h" +#include "../zprep.h" +#include "codegen.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> // Emit C preamble with standard includes and type definitions. void emit_preamble(FILE *out) @@ -14,15 +14,16 @@ void emit_preamble(FILE *out) { // Freestanding preamble. // It actually needs more work, but yk. - fputs( - "#include <stddef.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <stdarg.h>\n", - out); + fputs("#include <stddef.h>\n#include <stdint.h>\n#include " + "<stdbool.h>\n#include <stdarg.h>\n", + out); fputs("#ifdef __TINYC__\n#define __auto_type __typeof__\n#endif\n", out); fputs("typedef size_t usize;\ntypedef char* string;\n", out); fputs("#define U0 void\n#define I8 int8_t\n#define U8 uint8_t\n#define I16 " "int16_t\n#define U16 uint16_t\n", out); - fputs("#define I32 int32_t\n#define U32 uint32_t\n#define I64 int64_t\n#define U64 " + fputs("#define I32 int32_t\n#define U32 uint32_t\n#define I64 " + "int64_t\n#define U64 " "uint64_t\n", out); fputs("#define F32 float\n#define F64 double\n", out); @@ -36,7 +37,9 @@ void emit_preamble(FILE *out) fputs("typedef struct { void *func; void *ctx; } z_closure_T;\n", out); fputs("__attribute__((weak)) void* z_malloc(usize sz) { return NULL; }\n", out); - fputs("__attribute__((weak)) void* z_realloc(void* ptr, usize sz) { return NULL; }\n", out); + fputs("__attribute__((weak)) void* z_realloc(void* ptr, usize sz) { return " + "NULL; }\n", + out); fputs("__attribute__((weak)) void z_free(void* ptr) { }\n", out); fputs("__attribute__((weak)) void z_print(const char* fmt, ...) { }\n", out); fputs("__attribute__((weak)) void z_panic(const char* msg) { while(1); }\n", out); @@ -44,7 +47,8 @@ void emit_preamble(FILE *out) else { // Standard hosted preamble. - fputs("#include <stdio.h>\n#include <stdlib.h>\n#include <stddef.h>\n#include <string.h>\n", + fputs("#include <stdio.h>\n#include <stdlib.h>\n#include " + "<stddef.h>\n#include <string.h>\n", out); fputs("#include <stdarg.h>\n#include <stdint.h>\n#include <stdbool.h>\n", out); fputs("#include <unistd.h>\n#include <fcntl.h>\n", out); // POSIX functions @@ -56,7 +60,8 @@ void emit_preamble(FILE *out) fputs("#define U0 void\n#define I8 int8_t\n#define U8 uint8_t\n#define I16 " "int16_t\n#define U16 uint16_t\n", out); - fputs("#define I32 int32_t\n#define U32 uint32_t\n#define I64 int64_t\n#define U64 " + fputs("#define I32 int32_t\n#define U32 uint32_t\n#define I64 " + "int64_t\n#define U64 " "uint64_t\n", out); fputs("#define F32 float\n#define F64 double\n", out); @@ -69,25 +74,32 @@ void emit_preamble(FILE *out) out); // Memory Mapping. - fputs("#define z_malloc malloc\n#define z_realloc realloc\n#define z_free free\n#define " + fputs("#define z_malloc malloc\n#define z_realloc realloc\n#define z_free " + "free\n#define " "z_print printf\n", out); - fputs( - "void z_panic(const char* msg) { fprintf(stderr, \"Panic: %s\\n\", msg); exit(1); }\n", - out); + fputs("void z_panic(const char* msg) { fprintf(stderr, \"Panic: %s\\n\", " + "msg); exit(1); }\n", + out); - fputs("void _z_autofree_impl(void *p) { void **pp = (void**)p; if(*pp) { z_free(*pp); *pp " + fputs("void _z_autofree_impl(void *p) { void **pp = (void**)p; if(*pp) { " + "z_free(*pp); *pp " "= NULL; } }\n", out); - fputs("#define assert(cond, ...) if (!(cond)) { fprintf(stderr, \"Assertion failed: \" " + fputs("#define assert(cond, ...) if (!(cond)) { fprintf(stderr, " + "\"Assertion failed: \" " "__VA_ARGS__); exit(1); }\n", out); - fputs("string _z_readln_raw() { char *line = NULL; size_t len = 0; if(getline(&line, &len, " - "stdin) == -1) return NULL; if(strlen(line) > 0 && line[strlen(line)-1] == '\\n') " + fputs("string _z_readln_raw() { char *line = NULL; size_t len = 0; " + "if(getline(&line, &len, " + "stdin) == -1) return NULL; if(strlen(line) > 0 && " + "line[strlen(line)-1] == '\\n') " "line[strlen(line)-1] = 0; return line; }\n", out); - fputs("int _z_scan_helper(const char *fmt, ...) { char *l = _z_readln_raw(); if(!l) return " - "0; va_list ap; va_start(ap, fmt); int r = vsscanf(l, fmt, ap); va_end(ap); " + fputs("int _z_scan_helper(const char *fmt, ...) { char *l = " + "_z_readln_raw(); if(!l) return " + "0; va_list ap; va_start(ap, fmt); int r = vsscanf(l, fmt, ap); " + "va_end(ap); " "z_free(l); return r; }\n", out); @@ -235,6 +247,13 @@ void emit_struct_defs(ParserContext *ctx, ASTNode *node, FILE *out) } if (node->type == NODE_STRUCT) { + if (node->strct.is_incomplete) + { + // Forward declaration - no body needed (typedef handles it) + node = node->next; + continue; + } + if (node->strct.is_union) { fprintf(out, "union %s {", node->strct.name); @@ -763,35 +782,40 @@ void print_type_defs(ParserContext *ctx, FILE *out, ASTNode *nodes) fprintf(out, "typedef struct { void **data; int len; int cap; } Vec;\n"); fprintf(out, "#define Vec_new() (Vec){.data=0, .len=0, .cap=0}\n"); - fprintf( - out, - "void _z_vec_push(Vec *v, void *item) { if(v->len >= v->cap) { v->cap = v->cap?v->cap*2:8; " - "v->data = z_realloc(v->data, v->cap * sizeof(void*)); } v->data[v->len++] = item; }\n"); + fprintf(out, "void _z_vec_push(Vec *v, void *item) { if(v->len >= v->cap) { " + "v->cap = v->cap?v->cap*2:8; " + "v->data = z_realloc(v->data, v->cap * sizeof(void*)); } " + "v->data[v->len++] = item; }\n"); fprintf(out, "#define Vec_push(v, i) _z_vec_push(&(v), (void*)(long)(i))\n"); - fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = count > 8 ? " - "count : 8; v.data = z_malloc(v.cap * sizeof(void*)); v.len = 0; va_list args; " + fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = " + "count > 8 ? " + "count : 8; v.data = z_malloc(v.cap * sizeof(void*)); v.len = 0; va_list " + "args; " "va_start(args, count); for(int i=0; i<count; i++) { v.data[v.len++] = " "va_arg(args, void*); } va_end(args); return v; }\n"); if (g_config.is_freestanding) { - fprintf(out, "#define _z_check_bounds(index, limit) ({ __auto_type _i = (index); if(_i < 0 " + fprintf(out, "#define _z_check_bounds(index, limit) ({ __auto_type _i = " + "(index); if(_i < 0 " "|| _i >= (limit)) { z_panic(\"index out of bounds\"); } _i; })\n"); } else { - fprintf(out, "#define _z_check_bounds(index, limit) ({ __auto_type _i = (index); if(_i < 0 " - "|| _i >= (limit)) { fprintf(stderr, \"Index out of bounds: %%ld (limit " + fprintf(out, "#define _z_check_bounds(index, limit) ({ __auto_type _i = " + "(index); if(_i < 0 " + "|| _i >= (limit)) { fprintf(stderr, \"Index out of bounds: " + "%%ld (limit " "%%d)\\n\", (long)_i, (int)(limit)); exit(1); } _i; })\n"); } SliceType *c = ctx->used_slices; while (c) { - fprintf( - out, - "typedef struct Slice_%s Slice_%s;\nstruct Slice_%s { %s *data; int len; int cap; };\n", - c->name, c->name, c->name, c->name); + fprintf(out, + "typedef struct Slice_%s Slice_%s;\nstruct Slice_%s { %s *data; " + "int len; int cap; };\n", + c->name, c->name, c->name, c->name); c = c->next; } @@ -814,8 +838,8 @@ void print_type_defs(ParserContext *ctx, FILE *out, ASTNode *nodes) } fprintf(out, "\n"); - // FIRST: Emit typedefs for ALL structs and enums in the current compilation unit (local - // definitions) + // FIRST: Emit typedefs for ALL structs and enums in the current compilation + // unit (local definitions) ASTNode *local = nodes; while (local) { diff --git a/src/codegen/codegen_main.c b/src/codegen/codegen_main.c index 0e10869..c9c69f6 100644 --- a/src/codegen/codegen_main.c +++ b/src/codegen/codegen_main.c @@ -1,10 +1,10 @@ +#include "../ast/ast.h" +#include "../zprep.h" +#include "codegen.h" #include <stdio.h> -#include <string.h> #include <stdlib.h> -#include "codegen.h" -#include "../zprep.h" -#include "../ast/ast.h" +#include <string.h> // Helper: Check if a struct depends on another struct/enum by-value. static int struct_depends_on(ASTNode *s1, const char *target_name) @@ -191,7 +191,8 @@ void codegen_node(ParserContext *ctx, ASTNode *node, FILE *out) if (node->type == NODE_ROOT) { ASTNode *kids = node->root.children; - // Recursive Unwrap of Nested Roots (if accidentally wrapped multiple times). + // Recursive Unwrap of Nested Roots (if accidentally wrapped multiple + // times). while (kids && kids->type == NODE_ROOT) { kids = kids->root.children; diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c index fac6c6d..5dcbf19 100644 --- a/src/codegen/codegen_utils.c +++ b/src/codegen/codegen_utils.c @@ -1,12 +1,12 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include "codegen.h" -#include "../zprep.h" #include "../ast/ast.h" #include "../parser/parser.h" +#include "../zprep.h" +#include "codegen.h" +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> // Global state ASTNode *global_user_structs = NULL; @@ -44,7 +44,7 @@ ASTNode *find_struct_def_codegen(ParserContext *ctx, const char *name) ASTNode *s = global_user_structs; while (s) { - if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0) + if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0 && !s->strct.is_incomplete) { return s; } @@ -55,7 +55,8 @@ ASTNode *find_struct_def_codegen(ParserContext *ctx, const char *name) StructRef *sr = ctx->parsed_structs_list; while (sr) { - if (sr->node && sr->node->type == NODE_STRUCT && strcmp(sr->node->strct.name, name) == 0) + if (sr->node && sr->node->type == NODE_STRUCT && strcmp(sr->node->strct.name, name) == 0 && + !sr->node->strct.is_incomplete) { return sr->node; } @@ -64,7 +65,7 @@ ASTNode *find_struct_def_codegen(ParserContext *ctx, const char *name) s = ctx->instantiated_structs; while (s) { - if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0) + if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0 && !s->strct.is_incomplete) { return s; } |
