summaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.c26
-rw-r--r--src/codegen/codegen.h4
-rw-r--r--src/codegen/codegen_decl.c98
-rw-r--r--src/codegen/codegen_main.c11
-rw-r--r--src/codegen/codegen_utils.c19
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;
}