| author | |
| committer | |
| log | cb4773ce29fbac856811f69a3fb5b17b7e83d44d |
| tree | 5c87a210beae92c243dcd7818865447b35d44be5 |
| parent | 4cc95174a77f7cbb42b371bb892c55a8349bc7fa |
10 files changed, 206 insertions(+), 30 deletions(-)
README.md+6-2| ... | ... | @@ -32,7 +32,9 @@ readable, safe, optimal, and concise code to solve any computing problem. |
| 32 | 32 | |
| 33 | 33 | ## Roadmap |
| 34 | 34 | |
| 35 | * Simple .so library | |
| 35 | * Math expression | |
| 36 | * Export .so library | |
| 37 | * Export .o file | |
| 36 | 38 | * Multiple files |
| 37 | 39 | * inline assembly and syscalls |
| 38 | 40 | * running code at compile time |
| ... | ... | @@ -66,7 +68,9 @@ zig | C equivalent | Description |
| 66 | 68 | ### Grammar |
| 67 | 69 | |
| 68 | 70 | ``` |
| 69 | Root : many(TopLevelDecl) token(EOF) | |
| 71 | Root : RootExportDecl many(TopLevelDecl) token(EOF) | |
| 72 | ||
| 73 | RootExportDecl : token(Export) token(Symbol) token(String) token(Semicolon) | |
| 70 | 74 | |
| 71 | 75 | TopLevelDecl : FnDef | ExternBlock |
| 72 | 76 |
doc/vim/syntax/zig.vim+15| ... | ... | @@ -10,7 +10,22 @@ endif |
| 10 | 10 | syn keyword zigKeyword fn return mut const extern unreachable export pub |
| 11 | 11 | syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void |
| 12 | 12 | |
| 13 | syn region zigCommentLine start="//" end="$" contains=zigTodo,@Spell | |
| 14 | syn region zigCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=zigTodo,@Spell | |
| 15 | syn region zigCommentBlock matchgroup=zigCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=zigTodo,zigCommentBlockNest,@Spell | |
| 16 | syn region zigCommentBlockDoc matchgroup=zigCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=zigTodo,zigCommentBlockDocNest,@Spell | |
| 17 | syn region zigCommentBlockNest matchgroup=zigCommentBlock start="/\*" end="\*/" contains=zigTodo,zigCommentBlockNest,@Spell contained transparent | |
| 18 | syn region zigCommentBlockDocNest matchgroup=zigCommentBlockDoc start="/\*" end="\*/" contains=zigTodo,zigCommentBlockDocNest,@Spell contained transparent | |
| 19 | ||
| 20 | syn keyword zigTodo contained TODO XXX | |
| 21 | ||
| 13 | 22 | let b:current_syntax = "zig" |
| 14 | 23 | |
| 15 | 24 | hi def link zigKeyword Keyword |
| 16 | 25 | hi def link zigType Type |
| 26 | hi def link zigCommentLine Comment | |
| 27 | hi def link zigCommentLineDoc SpecialComment | |
| 28 | hi def link zigCommentBlock zigCommentLine | |
| 29 | hi def link zigCommentBlockDoc zigCommentLineDoc | |
| 30 | hi def link zigTodo Todo | |
| 31 |
example/hello.zig+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | export executable "hello"; | |
| 2 | ||
| 1 | 3 | #link("c") |
| 2 | 4 | extern { |
| 3 | 5 | fn puts(s: *mut u8) -> i32; |
example/math.zig created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | export library "math"; | |
| 2 | ||
| 3 | export fn add(a: i32, b: i32) -> i32 { | |
| 4 | return a + b; | |
| 5 | } | |
| 6 |
src/codegen.cpp+70-8| ... | ... | @@ -75,6 +75,8 @@ struct CodeGen { |
| 75 | 75 | ZigList<llvm::DIScope *> block_scopes; |
| 76 | 76 | llvm::DIFile *di_file; |
| 77 | 77 | ZigList<FnTableEntry *> fn_defs; |
| 78 | Buf *out_name; | |
| 79 | OutType out_type; | |
| 78 | 80 | }; |
| 79 | 81 | |
| 80 | 82 | struct TypeNode { |
| ... | ... | @@ -103,6 +105,8 @@ CodeGen *create_codegen(AstNode *root, Buf *in_full_path) { |
| 103 | 105 | g->is_static = false; |
| 104 | 106 | g->build_type = CodeGenBuildTypeDebug; |
| 105 | 107 | g->strip_debug_symbols = false; |
| 108 | g->out_name = nullptr; | |
| 109 | g->out_type = OutTypeUnknown; | |
| 106 | 110 | |
| 107 | 111 | os_path_split(in_full_path, &g->in_dir, &g->in_file); |
| 108 | 112 | return g; |
| ... | ... | @@ -120,6 +124,14 @@ void codegen_set_strip(CodeGen *g, bool strip) { |
| 120 | 124 | g->strip_debug_symbols = strip; |
| 121 | 125 | } |
| 122 | 126 | |
| 127 | void codegen_set_out_type(CodeGen *g, OutType out_type) { | |
| 128 | g->out_type = out_type; | |
| 129 | } | |
| 130 | ||
| 131 | void codegen_set_out_name(CodeGen *g, Buf *out_name) { | |
| 132 | g->out_name = out_name; | |
| 133 | } | |
| 134 | ||
| 123 | 135 | static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 124 | 136 | g->errors.add_one(); |
| 125 | 137 | ErrorMsg *last_msg = &g->errors.last(); |
| ... | ... | @@ -294,6 +306,7 @@ static void find_declarations(CodeGen *g, AstNode *node) { |
| 294 | 306 | case NodeTypeBlock: |
| 295 | 307 | case NodeTypeExpression: |
| 296 | 308 | case NodeTypeFnCall: |
| 309 | case NodeTypeRootExportDecl: | |
| 297 | 310 | zig_unreachable(); |
| 298 | 311 | } |
| 299 | 312 | } |
| ... | ... | @@ -355,15 +368,50 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) { |
| 355 | 368 | static void analyze_node(CodeGen *g, AstNode *node) { |
| 356 | 369 | switch (node->type) { |
| 357 | 370 | case NodeTypeRoot: |
| 358 | // Iterate once over the top level declarations to build the function table | |
| 359 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { | |
| 360 | AstNode *child = node->data.root.top_level_decls.at(i); | |
| 361 | find_declarations(g, child); | |
| 362 | } | |
| 363 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { | |
| 364 | AstNode *child = node->data.root.top_level_decls.at(i); | |
| 365 | analyze_node(g, child); | |
| 371 | { | |
| 372 | AstNode *root_export_decl_node = node->data.root.root_export_decl; | |
| 373 | if (root_export_decl_node) { | |
| 374 | assert(root_export_decl_node->type == NodeTypeRootExportDecl); | |
| 375 | if (!g->out_name) | |
| 376 | g->out_name = &root_export_decl_node->data.root_export_decl.name; | |
| 377 | ||
| 378 | Buf *out_type = &root_export_decl_node->data.root_export_decl.type; | |
| 379 | OutType export_out_type; | |
| 380 | if (buf_eql_str(out_type, "executable")) { | |
| 381 | export_out_type = OutTypeExe; | |
| 382 | } else if (buf_eql_str(out_type, "library")) { | |
| 383 | export_out_type = OutTypeLib; | |
| 384 | } else if (buf_eql_str(out_type, "object")) { | |
| 385 | export_out_type = OutTypeObj; | |
| 386 | } else { | |
| 387 | add_node_error(g, root_export_decl_node, | |
| 388 | buf_sprintf("invalid export type: '%s'", buf_ptr(out_type))); | |
| 389 | } | |
| 390 | if (g->out_type == OutTypeUnknown) | |
| 391 | g->out_type = export_out_type; | |
| 392 | } else { | |
| 393 | if (!g->out_name) { | |
| 394 | add_node_error(g, node, | |
| 395 | buf_sprintf("missing export declaration and output name not provided")); | |
| 396 | } else if (g->out_type == OutTypeUnknown) { | |
| 397 | add_node_error(g, node, | |
| 398 | buf_sprintf("missing export declaration and export type not provided")); | |
| 399 | } | |
| 400 | } | |
| 401 | ||
| 402 | // Iterate once over the top level declarations to build the function table | |
| 403 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { | |
| 404 | AstNode *child = node->data.root.top_level_decls.at(i); | |
| 405 | find_declarations(g, child); | |
| 406 | } | |
| 407 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { | |
| 408 | AstNode *child = node->data.root.top_level_decls.at(i); | |
| 409 | analyze_node(g, child); | |
| 410 | } | |
| 411 | break; | |
| 366 | 412 | } |
| 413 | case NodeTypeRootExportDecl: | |
| 414 | // handled in parent | |
| 367 | 415 | break; |
| 368 | 416 | case NodeTypeExternBlock: |
| 369 | 417 | for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) { |
| ... | ... | @@ -674,6 +722,7 @@ static void gen_block(CodeGen *g, AstNode *block_node, bool add_implicit_return) |
| 674 | 722 | case NodeTypeFnCall: |
| 675 | 723 | case NodeTypeExternBlock: |
| 676 | 724 | case NodeTypeDirective: |
| 725 | case NodeTypeRootExportDecl: | |
| 677 | 726 | zig_unreachable(); |
| 678 | 727 | } |
| 679 | 728 | } |
| ... | ... | @@ -929,6 +978,15 @@ static Buf *get_dynamic_linker(CodeGen *g) { |
| 929 | 978 | } |
| 930 | 979 | } |
| 931 | 980 | |
| 981 | /* | |
| 982 | ||
| 983 | # static link into libfoo.a | |
| 984 | ar cq libfoo.a foo1.o foo2.o | |
| 985 | ||
| 986 | # dynamic link into libfoo.so | |
| 987 | gcc -fPIC -g -Werror -pedantic -shared -Wl,-soname,libsoundio.so.1 -o libsoundio.so.1.0.3 foo1.o foo2.o -ljack -lpulse -lasound -lpthread | |
| 988 | ||
| 989 | */ | |
| 932 | 990 | void code_gen_link(CodeGen *g, const char *out_file) { |
| 933 | 991 | LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry(); |
| 934 | 992 | LLVMInitializeCore(registry); |
| ... | ... | @@ -937,6 +995,10 @@ void code_gen_link(CodeGen *g, const char *out_file) { |
| 937 | 995 | LLVMZigInitializeLowerIntrinsicsPass(registry); |
| 938 | 996 | LLVMZigInitializeUnreachableBlockElimPass(registry); |
| 939 | 997 | |
| 998 | if (!out_file) { | |
| 999 | out_file = buf_ptr(g->out_name); | |
| 1000 | } | |
| 1001 | ||
| 940 | 1002 | Buf out_file_o = BUF_INIT; |
| 941 | 1003 | buf_init_from_str(&out_file_o, out_file); |
| 942 | 1004 | buf_append_str(&out_file_o, ".o"); |
src/codegen.hpp+10| ... | ... | @@ -12,6 +12,14 @@ |
| 12 | 12 | |
| 13 | 13 | struct CodeGen; |
| 14 | 14 | |
| 15 | enum OutType { | |
| 16 | OutTypeUnknown, | |
| 17 | OutTypeExe, | |
| 18 | OutTypeLib, | |
| 19 | OutTypeObj, | |
| 20 | }; | |
| 21 | ||
| 22 | ||
| 15 | 23 | struct ErrorMsg { |
| 16 | 24 | int line_start; |
| 17 | 25 | int column_start; |
| ... | ... | @@ -30,6 +38,8 @@ enum CodeGenBuildType { |
| 30 | 38 | void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type); |
| 31 | 39 | void codegen_set_is_static(CodeGen *codegen, bool is_static); |
| 32 | 40 | void codegen_set_strip(CodeGen *codegen, bool strip); |
| 41 | void codegen_set_out_type(CodeGen *codegen, OutType out_type); | |
| 42 | void codegen_set_out_name(CodeGen *codegen, Buf *out_name); | |
| 33 | 43 | |
| 34 | 44 | void semantic_analyze(CodeGen *g); |
| 35 | 45 |
src/main.cpp+45-20| ... | ... | @@ -28,18 +28,24 @@ |
| 28 | 28 | static int usage(const char *arg0) { |
| 29 | 29 | fprintf(stderr, "Usage: %s [command] [options] target\n" |
| 30 | 30 | "Commands:\n" |
| 31 | " build create an executable from target\n" | |
| 32 | "Options:\n" | |
| 33 | " --output output file\n" | |
| 34 | " --version print version number and exit\n" | |
| 35 | " -Ipath add path to header include path\n" | |
| 36 | " --release build with optimizations on\n" | |
| 37 | " --strip exclude debug symbols\n" | |
| 38 | " --static build a static executable\n" | |
| 31 | " build create executable, object, or library from target\n" | |
| 32 | " version print version number and exit\n" | |
| 33 | "Optional Options:\n" | |
| 34 | " --release build with optimizations on and debug protection off\n" | |
| 35 | " --static output will be statically linked\n" | |
| 36 | " --strip exclude debug symbols\n" | |
| 37 | " --export [exe|lib|obj] override output type\n" | |
| 38 | " --name [name] override output name\n" | |
| 39 | " --output [file] override destination path\n" | |
| 39 | 40 | , arg0); |
| 40 | 41 | return EXIT_FAILURE; |
| 41 | 42 | } |
| 42 | 43 | |
| 44 | static int version(void) { | |
| 45 | printf("%s\n", ZIG_VERSION_STRING); | |
| 46 | return EXIT_SUCCESS; | |
| 47 | } | |
| 48 | ||
| 43 | 49 | static Buf *fetch_file(FILE *f) { |
| 44 | 50 | int fd = fileno(f); |
| 45 | 51 | struct stat st; |
| ... | ... | @@ -58,12 +64,12 @@ static Buf *fetch_file(FILE *f) { |
| 58 | 64 | return buf; |
| 59 | 65 | } |
| 60 | 66 | |
| 61 | static int build(const char *arg0, const char *in_file, const char *out_file, | |
| 62 | ZigList<char *> *include_paths, bool release, bool strip, bool is_static) | |
| 67 | static int build(const char *arg0, const char *in_file, const char *out_file, bool release, | |
| 68 | bool strip, bool is_static, OutType out_type, char *out_name) | |
| 63 | 69 | { |
| 64 | 70 | static char cur_dir[1024]; |
| 65 | 71 | |
| 66 | if (!in_file || !out_file) | |
| 72 | if (!in_file) | |
| 67 | 73 | return usage(arg0); |
| 68 | 74 | |
| 69 | 75 | FILE *in_f; |
| ... | ... | @@ -100,6 +106,10 @@ static int build(const char *arg0, const char *in_file, const char *out_file, |
| 100 | 106 | codegen_set_build_type(codegen, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug); |
| 101 | 107 | codegen_set_strip(codegen, strip); |
| 102 | 108 | codegen_set_is_static(codegen, is_static); |
| 109 | if (out_type != OutTypeUnknown) | |
| 110 | codegen_set_out_type(codegen, out_type); | |
| 111 | if (out_name) | |
| 112 | codegen_set_out_name(codegen, buf_create_from_str(out_name)); | |
| 103 | 113 | semantic_analyze(codegen); |
| 104 | 114 | ZigList<ErrorMsg> *errors = codegen_error_messages(codegen); |
| 105 | 115 | if (errors->length == 0) { |
| ... | ... | @@ -135,25 +145,25 @@ static int build(const char *arg0, const char *in_file, const char *out_file, |
| 135 | 145 | enum Cmd { |
| 136 | 146 | CmdNone, |
| 137 | 147 | CmdBuild, |
| 148 | CmdVersion, | |
| 138 | 149 | }; |
| 139 | 150 | |
| 140 | 151 | int main(int argc, char **argv) { |
| 141 | 152 | char *arg0 = argv[0]; |
| 142 | 153 | char *in_file = NULL; |
| 143 | 154 | char *out_file = NULL; |
| 144 | ZigList<char *> include_paths = {0}; | |
| 145 | 155 | bool release = false; |
| 146 | 156 | bool strip = false; |
| 147 | 157 | bool is_static = false; |
| 148 | 158 | |
| 159 | OutType out_type = OutTypeUnknown; | |
| 160 | char *out_name = NULL; | |
| 161 | ||
| 149 | 162 | Cmd cmd = CmdNone; |
| 150 | 163 | for (int i = 1; i < argc; i += 1) { |
| 151 | 164 | char *arg = argv[i]; |
| 152 | 165 | if (arg[0] == '-' && arg[1] == '-') { |
| 153 | if (strcmp(arg, "--version") == 0) { | |
| 154 | printf("%s\n", ZIG_VERSION_STRING); | |
| 155 | return EXIT_SUCCESS; | |
| 156 | } else if (strcmp(arg, "--release") == 0) { | |
| 166 | if (strcmp(arg, "--release") == 0) { | |
| 157 | 167 | release = true; |
| 158 | 168 | } else if (strcmp(arg, "--strip") == 0) { |
| 159 | 169 | strip = true; |
| ... | ... | @@ -165,15 +175,27 @@ int main(int argc, char **argv) { |
| 165 | 175 | i += 1; |
| 166 | 176 | if (strcmp(arg, "--output") == 0) { |
| 167 | 177 | out_file = argv[i]; |
| 178 | } else if (strcmp(arg, "--export") == 0) { | |
| 179 | if (strcmp(argv[i], "exe") == 0) { | |
| 180 | out_type = OutTypeExe; | |
| 181 | } else if (strcmp(argv[i], "lib") == 0) { | |
| 182 | out_type = OutTypeLib; | |
| 183 | } else if (strcmp(argv[i], "obj") == 0) { | |
| 184 | out_type = OutTypeObj; | |
| 185 | } else { | |
| 186 | return usage(arg0); | |
| 187 | } | |
| 188 | } else if (strcmp(arg, "--name") == 0) { | |
| 189 | out_name = argv[i]; | |
| 168 | 190 | } else { |
| 169 | 191 | return usage(arg0); |
| 170 | 192 | } |
| 171 | 193 | } |
| 172 | } else if (arg[0] == '-' && arg[1] == 'I') { | |
| 173 | include_paths.append(arg + 2); | |
| 174 | 194 | } else if (cmd == CmdNone) { |
| 175 | 195 | if (strcmp(arg, "build") == 0) { |
| 176 | 196 | cmd = CmdBuild; |
| 197 | } else if (strcmp(arg, "version") == 0) { | |
| 198 | cmd = CmdVersion; | |
| 177 | 199 | } else { |
| 178 | 200 | fprintf(stderr, "Unrecognized command: %s\n", arg); |
| 179 | 201 | return usage(arg0); |
| ... | ... | @@ -189,6 +211,8 @@ int main(int argc, char **argv) { |
| 189 | 211 | return usage(arg0); |
| 190 | 212 | } |
| 191 | 213 | break; |
| 214 | case CmdVersion: | |
| 215 | return usage(arg0); | |
| 192 | 216 | } |
| 193 | 217 | } |
| 194 | 218 | } |
| ... | ... | @@ -197,9 +221,10 @@ int main(int argc, char **argv) { |
| 197 | 221 | case CmdNone: |
| 198 | 222 | return usage(arg0); |
| 199 | 223 | case CmdBuild: |
| 200 | return build(arg0, in_file, out_file, &include_paths, release, strip, is_static); | |
| 224 | return build(arg0, in_file, out_file, release, strip, is_static, out_type, out_name); | |
| 225 | case CmdVersion: | |
| 226 | return version(); | |
| 201 | 227 | } |
| 202 | 228 | |
| 203 | 229 | zig_unreachable(); |
| 204 | 230 | } |
| 205 |
src/parser.cpp+40| ... | ... | @@ -29,6 +29,8 @@ const char *node_type_str(NodeType node_type) { |
| 29 | 29 | switch (node_type) { |
| 30 | 30 | case NodeTypeRoot: |
| 31 | 31 | return "Root"; |
| 32 | case NodeTypeRootExportDecl: | |
| 33 | return "RootExportDecl"; | |
| 32 | 34 | case NodeTypeFnDef: |
| 33 | 35 | return "FnDef"; |
| 34 | 36 | case NodeTypeFnDecl: |
| ... | ... | @@ -68,6 +70,11 @@ void ast_print(AstNode *node, int indent) { |
| 68 | 70 | ast_print(child, indent + 2); |
| 69 | 71 | } |
| 70 | 72 | break; |
| 73 | case NodeTypeRootExportDecl: | |
| 74 | fprintf(stderr, "%s %s '%s'\n", node_type_str(node->type), | |
| 75 | buf_ptr(&node->data.root_export_decl.type), | |
| 76 | buf_ptr(&node->data.root_export_decl.name)); | |
| 77 | break; | |
| 71 | 78 | case NodeTypeFnDef: |
| 72 | 79 | { |
| 73 | 80 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| ... | ... | @@ -714,6 +721,36 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 714 | 721 | zig_unreachable(); |
| 715 | 722 | } |
| 716 | 723 | |
| 724 | static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index) { | |
| 725 | Token *export_kw = &pc->tokens->at(*token_index); | |
| 726 | if (export_kw->id != TokenIdKeywordExport) | |
| 727 | return nullptr; | |
| 728 | *token_index += 1; | |
| 729 | ||
| 730 | AstNode *node = ast_create_node(NodeTypeRootExportDecl, export_kw); | |
| 731 | ||
| 732 | Token *export_type = &pc->tokens->at(*token_index); | |
| 733 | *token_index += 1; | |
| 734 | ast_expect_token(pc, export_type, TokenIdSymbol); | |
| 735 | ||
| 736 | ast_buf_from_token(pc, export_type, &node->data.root_export_decl.type); | |
| 737 | ||
| 738 | Token *export_name = &pc->tokens->at(*token_index); | |
| 739 | *token_index += 1; | |
| 740 | ast_expect_token(pc, export_name, TokenIdStringLiteral); | |
| 741 | ||
| 742 | parse_string_literal(pc, export_name, &node->data.root_export_decl.name); | |
| 743 | ||
| 744 | Token *semicolon = &pc->tokens->at(*token_index); | |
| 745 | *token_index += 1; | |
| 746 | ast_expect_token(pc, semicolon, TokenIdSemicolon); | |
| 747 | ||
| 748 | return node; | |
| 749 | } | |
| 750 | ||
| 751 | /* | |
| 752 | Root : RootExportDecl many(TopLevelDecl) token(EOF) | |
| 753 | */ | |
| 717 | 754 | AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) { |
| 718 | 755 | ParseContext pc = {0}; |
| 719 | 756 | pc.buf = buf; |
| ... | ... | @@ -721,6 +758,9 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) { |
| 721 | 758 | pc.tokens = tokens; |
| 722 | 759 | |
| 723 | 760 | int token_index = 0; |
| 761 | ||
| 762 | pc.root->data.root.root_export_decl = ast_parse_root_export_decl(&pc, &token_index); | |
| 763 | ||
| 724 | 764 | ast_parse_top_level_decls(&pc, &token_index, &pc.root->data.root.top_level_decls); |
| 725 | 765 | |
| 726 | 766 | if (token_index != tokens->length - 1) { |
src/parser.hpp+8| ... | ... | @@ -17,6 +17,7 @@ struct CodeGenNode; |
| 17 | 17 | |
| 18 | 18 | enum NodeType { |
| 19 | 19 | NodeTypeRoot, |
| 20 | NodeTypeRootExportDecl, | |
| 20 | 21 | NodeTypeFnProto, |
| 21 | 22 | NodeTypeFnDef, |
| 22 | 23 | NodeTypeFnDecl, |
| ... | ... | @@ -31,6 +32,7 @@ enum NodeType { |
| 31 | 32 | }; |
| 32 | 33 | |
| 33 | 34 | struct AstNodeRoot { |
| 35 | AstNode *root_export_decl; | |
| 34 | 36 | ZigList<AstNode *> top_level_decls; |
| 35 | 37 | }; |
| 36 | 38 | |
| ... | ... | @@ -113,6 +115,11 @@ struct AstNodeDirective { |
| 113 | 115 | Buf param; |
| 114 | 116 | }; |
| 115 | 117 | |
| 118 | struct AstNodeRootExportDecl { | |
| 119 | Buf type; | |
| 120 | Buf name; | |
| 121 | }; | |
| 122 | ||
| 116 | 123 | struct AstNode { |
| 117 | 124 | enum NodeType type; |
| 118 | 125 | AstNode *parent; |
| ... | ... | @@ -121,6 +128,7 @@ struct AstNode { |
| 121 | 128 | CodeGenNode *codegen_node; |
| 122 | 129 | union { |
| 123 | 130 | AstNodeRoot root; |
| 131 | AstNodeRootExportDecl root_export_decl; | |
| 124 | 132 | AstNodeFnDef fn_def; |
| 125 | 133 | AstNodeFnDecl fn_decl; |
| 126 | 134 | AstNodeFnProto fn_proto; |
test/run_tests.cpp+4| ... | ... | @@ -39,6 +39,10 @@ static void add_simple_case(const char *case_name, const char *source, const cha |
| 39 | 39 | |
| 40 | 40 | test_case->compiler_args.append("build"); |
| 41 | 41 | test_case->compiler_args.append(tmp_source_path); |
| 42 | test_case->compiler_args.append("--export"); | |
| 43 | test_case->compiler_args.append("exe"); | |
| 44 | test_case->compiler_args.append("--name"); | |
| 45 | test_case->compiler_args.append("test"); | |
| 42 | 46 | test_case->compiler_args.append("--output"); |
| 43 | 47 | test_case->compiler_args.append(tmp_exe_path); |
| 44 | 48 | test_case->compiler_args.append("--release"); |