diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen/codegen.c | 12 | ||||
| -rw-r--r-- | src/codegen/codegen_decl.c | 150 | ||||
| -rw-r--r-- | src/codegen/codegen_utils.c | 2 | ||||
| -rw-r--r-- | src/codegen/compat.h | 100 | ||||
| -rw-r--r-- | src/main.c | 8 | ||||
| -rw-r--r-- | src/zprep.h | 1 |
6 files changed, 227 insertions, 46 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 25ae5b3..1d825dc 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -174,7 +174,7 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, } else { - fprintf(out, "__auto_type %s = _m_%d.val; ", c->match_case.binding_name, id); + fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name, id); } } if (is_result) @@ -188,8 +188,7 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, } else { - fprintf(out, "__auto_type %s = _m_%d.val; ", c->match_case.binding_name, - id); + fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name, id); } } else @@ -201,8 +200,7 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, } else { - fprintf(out, "__auto_type %s = _m_%d.err; ", c->match_case.binding_name, - id); + fprintf(out, "ZC_AUTO %s = _m_%d.err; ", c->match_case.binding_name, id); } } } @@ -217,7 +215,7 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, { f = c->match_case.pattern; } - fprintf(out, "__auto_type %s = _m_%d.data.%s; ", c->match_case.binding_name, id, f); + fprintf(out, "ZC_AUTO %s = _m_%d.data.%s; ", c->match_case.binding_name, id, f); } } @@ -1838,7 +1836,7 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) } else { - fprintf(out, "__auto_type %s = ", node->for_range.var_name); + fprintf(out, "ZC_AUTO %s = ", node->for_range.var_name); } codegen_expression(ctx, node->for_range.start, out); fprintf(out, "; %s < ", node->for_range.var_name); diff --git a/src/codegen/codegen_decl.c b/src/codegen/codegen_decl.c index 11970a5..e42d83b 100644 --- a/src/codegen/codegen_decl.c +++ b/src/codegen/codegen_decl.c @@ -52,7 +52,43 @@ void emit_preamble(ParserContext *ctx, FILE *out) 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 - fputs("#ifdef __TINYC__\n#define __auto_type __typeof__\n#endif\n", out); + + // C++ compatibility + if (g_config.use_cpp) + { + // For C++: define ZC_AUTO as auto, include compat.h macros inline + fputs("#define ZC_AUTO auto\n", out); + fputs("#define ZC_CAST(T, x) static_cast<T>(x)\n", out); + // C++ _z_str via overloads + fputs("inline const char* _z_str(bool) { return \"%d\"; }\n", out); + fputs("inline const char* _z_str(char) { return \"%c\"; }\n", out); + fputs("inline const char* _z_str(int) { return \"%d\"; }\n", out); + fputs("inline const char* _z_str(unsigned int) { return \"%u\"; }\n", out); + fputs("inline const char* _z_str(long) { return \"%ld\"; }\n", out); + fputs("inline const char* _z_str(unsigned long) { return \"%lu\"; }\n", out); + fputs("inline const char* _z_str(long long) { return \"%lld\"; }\n", out); + fputs("inline const char* _z_str(unsigned long long) { return \"%llu\"; }\n", out); + fputs("inline const char* _z_str(float) { return \"%f\"; }\n", out); + fputs("inline const char* _z_str(double) { return \"%f\"; }\n", out); + fputs("inline const char* _z_str(char*) { return \"%s\"; }\n", out); + fputs("inline const char* _z_str(const char*) { return \"%s\"; }\n", out); + fputs("inline const char* _z_str(void*) { return \"%p\"; }\n", out); + } + else + { + // C mode + fputs("#define ZC_AUTO __auto_type\n", out); + fputs("#define ZC_CAST(T, x) ((T)(x))\n", out); + fputs("#ifdef __TINYC__\n#define __auto_type __typeof__\n#endif\n", out); + fputs("#define _z_str(x) _Generic((x), _Bool: \"%d\", char: \"%c\", " + "signed char: \"%c\", unsigned char: \"%u\", short: \"%d\", " + "unsigned short: \"%u\", int: \"%d\", unsigned int: \"%u\", " + "long: \"%ld\", unsigned long: \"%lu\", long long: \"%lld\", " + "unsigned long long: \"%llu\", float: \"%f\", double: \"%f\", " + "char*: \"%s\", void*: \"%p\")\n", + out); + } + fputs("typedef size_t usize;\ntypedef char* string;\n", out); if (ctx->has_async) { @@ -68,19 +104,19 @@ void emit_preamble(ParserContext *ctx, FILE *out) "uint64_t\n", out); fputs("#define F32 float\n#define F64 double\n", out); - fputs("#define _z_str(x) _Generic((x), _Bool: \"%d\", char: \"%c\", " - "signed char: \"%c\", unsigned char: \"%u\", short: \"%d\", " - "unsigned short: \"%u\", int: \"%d\", unsigned int: \"%u\", " - "long: \"%ld\", unsigned long: \"%lu\", long long: \"%lld\", " - "unsigned long long: \"%llu\", float: \"%f\", double: \"%f\", " - "char*: \"%s\", void*: \"%p\")\n", - out); // Memory Mapping. - fputs("#define z_malloc malloc\n#define z_realloc realloc\n#define z_free " - "free\n#define " - "z_print printf\n", - out); + if (g_config.use_cpp) + { + // C++ needs explicit casts for void* conversions + fputs("#define z_malloc(sz) static_cast<char*>(malloc(sz))\n", out); + fputs("#define z_realloc(p, sz) static_cast<char*>(realloc(p, sz))\n", out); + } + else + { + fputs("#define z_malloc malloc\n#define z_realloc realloc\n", out); + } + fputs("#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); @@ -93,19 +129,41 @@ void emit_preamble(ParserContext *ctx, FILE *out) "\"Assertion failed: \" " "__VA_ARGS__); exit(1); }\n", out); - fputs("string _z_readln_raw() { " - "size_t cap = 64; size_t len = 0; " - "char *line = z_malloc(cap); " - "if(!line) return NULL; " - "int c; " - "while((c = fgetc(stdin)) != EOF) { " - "if(c == '\\n') break; " - "if(len + 1 >= cap) { cap *= 2; char *n = z_realloc(line, cap); " - "if(!n) { z_free(line); return NULL; } line = n; } " - "line[len++] = c; } " - "if(len == 0 && c == EOF) { z_free(line); return NULL; } " - "line[len] = 0; return line; }\n", - out); + + // C++ compatible readln helper + if (g_config.use_cpp) + { + fputs( + "string _z_readln_raw() { " + "size_t cap = 64; size_t len = 0; " + "char *line = static_cast<char*>(malloc(cap)); " + "if(!line) return NULL; " + "int c; " + "while((c = fgetc(stdin)) != EOF) { " + "if(c == '\\n') break; " + "if(len + 1 >= cap) { cap *= 2; char *n = static_cast<char*>(realloc(line, cap)); " + "if(!n) { free(line); return NULL; } line = n; } " + "line[len++] = c; } " + "if(len == 0 && c == EOF) { free(line); return NULL; } " + "line[len] = 0; return line; }\n", + out); + } + else + { + fputs("string _z_readln_raw() { " + "size_t cap = 64; size_t len = 0; " + "char *line = z_malloc(cap); " + "if(!line) return NULL; " + "int c; " + "while((c = fgetc(stdin)) != EOF) { " + "if(c == '\\n') break; " + "if(len + 1 >= cap) { cap *= 2; char *n = z_realloc(line, cap); " + "if(!n) { z_free(line); return NULL; } line = n; } " + "line[len++] = c; } " + "if(len == 0 && c == EOF) { z_free(line); return NULL; } " + "line[len] = 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); " @@ -809,27 +867,45 @@ 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"); + + if (g_config.use_cpp) + { + 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 = static_cast<void**>(realloc(v->data, v->cap * sizeof(void*))); } " + "v->data[v->len++] = item; }\n"); + fprintf(out, "static inline Vec _z_make_vec(int count, ...) { Vec v = {0}; v.cap = " + "count > 8 ? " + "count : 8; v.data = static_cast<void**>(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"); + } + else + { + 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, "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"); + } 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; " - "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 = " + fprintf(out, "#define _z_check_bounds(index, limit) ({ ZC_AUTO _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 = " + fprintf(out, "#define _z_check_bounds(index, limit) ({ ZC_AUTO _i = " "(index); if(_i < 0 " "|| _i >= (limit)) { fprintf(stderr, \"Index out of bounds: " "%%ld (limit " diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c index 392557f..b1fcf4c 100644 --- a/src/codegen/codegen_utils.c +++ b/src/codegen/codegen_utils.c @@ -515,7 +515,7 @@ void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t, FILE *out) } else { - fprintf(out, "__auto_type"); + fprintf(out, "ZC_AUTO"); } } } diff --git a/src/codegen/compat.h b/src/codegen/compat.h new file mode 100644 index 0000000..423b1d9 --- /dev/null +++ b/src/codegen/compat.h @@ -0,0 +1,100 @@ + +#ifndef ZC_COMPAT_H +#define ZC_COMPAT_H + +#ifdef __cplusplus +/* C++ mode */ +#define ZC_AUTO auto +#define ZC_CAST(T, x) static_cast<T>(x) +#define ZC_REINTERPRET(T, x) reinterpret_cast<T>(x) +#define ZC_EXTERN_C extern "C" +#define ZC_EXTERN_C_BEGIN \ + extern "C" \ + { +#define ZC_EXTERN_C_END } +#else +/* C mode */ +#define ZC_AUTO __auto_type +#define ZC_CAST(T, x) ((T)(x)) +#define ZC_REINTERPRET(T, x) ((T)(x)) +#define ZC_EXTERN_C +#define ZC_EXTERN_C_BEGIN +#define ZC_EXTERN_C_END +#endif + +#ifdef __cplusplus +#include <type_traits> + +inline const char *_zc_fmt(bool) +{ + return "%d"; +} +inline const char *_zc_fmt(char) +{ + return "%c"; +} +inline const char *_zc_fmt(signed char) +{ + return "%c"; +} +inline const char *_zc_fmt(unsigned char) +{ + return "%u"; +} +inline const char *_zc_fmt(short) +{ + return "%d"; +} +inline const char *_zc_fmt(unsigned short) +{ + return "%u"; +} +inline const char *_zc_fmt(int) +{ + return "%d"; +} +inline const char *_zc_fmt(unsigned int) +{ + return "%u"; +} +inline const char *_zc_fmt(long) +{ + return "%ld"; +} +inline const char *_zc_fmt(unsigned long) +{ + return "%lu"; +} +inline const char *_zc_fmt(long long) +{ + return "%lld"; +} +inline const char *_zc_fmt(unsigned long long) +{ + return "%llu"; +} +inline const char *_zc_fmt(float) +{ + return "%f"; +} +inline const char *_zc_fmt(double) +{ + return "%f"; +} +inline const char *_zc_fmt(char *) +{ + return "%s"; +} +inline const char *_zc_fmt(const char *) +{ + return "%s"; +} +inline const char *_zc_fmt(void *) +{ + return "%p"; +} + +#define _z_str(x) _zc_fmt(x) +#endif + +#endif @@ -37,7 +37,7 @@ void print_usage() printf(" transpile Transpile to C code only (no compilation)\n"); printf(" lsp Start Language Server\n"); printf("Options:\n"); - printf(" --version Print version information"); + printf(" --version Print version information\n"); printf(" -o <file> Output executable name\n"); printf(" --emit-c Keep generated C file (out.c)\n"); printf(" --freestanding Freestanding mode (no stdlib)\n"); @@ -47,6 +47,7 @@ void print_usage() printf(" -v, --verbose Verbose output\n"); printf(" -q, --quiet Quiet output\n"); printf(" -c Compile only (produce .o)\n"); + printf(" --cpp Use C++ mode.\n"); } int main(int argc, char **argv) @@ -141,6 +142,11 @@ int main(int argc, char **argv) { g_config.is_freestanding = 1; } + else if (strcmp(arg, "--cpp") == 0) + { + strcpy(g_config.cc, "g++"); + g_config.use_cpp = 1; + } else if (strcmp(arg, "--check") == 0) { g_config.mode_check = 1; diff --git a/src/zprep.h b/src/zprep.h index bf770a3..8a4ba3e 100644 --- a/src/zprep.h +++ b/src/zprep.h @@ -179,6 +179,7 @@ typedef struct int repl_mode; // 1 if --repl (internal flag for REPL usage). int is_freestanding; // 1 if --freestanding. int mode_transpile; // 1 if 'transpile' command. + int use_cpp; // 1 if --cpp (emit C++ compatible code). // GCC Flags accumulator. char gcc_flags[4096]; |
