authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-27 21:24:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-27 21:24:47-07:00
logcb4773ce29fbac856811f69a3fb5b17b7e83d44d
tree5c87a210beae92c243dcd7818865447b35d44be5
parent4cc95174a77f7cbb42b371bb892c55a8349bc7fa

add root export declaration which is overridable by command line options


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,7 +32,9 @@ readable, safe, optimal, and concise code to solve any computing problem.
3232
33## Roadmap33## Roadmap
3434
35 * Simple .so library35 * Math expression
36 * Export .so library
37 * Export .o file
36 * Multiple files38 * Multiple files
37 * inline assembly and syscalls39 * inline assembly and syscalls
38 * running code at compile time40 * running code at compile time
...@@ -66,7 +68,9 @@ zig | C equivalent | Description...@@ -66,7 +68,9 @@ zig | C equivalent | Description
66### Grammar68### Grammar
6769
68```70```
69Root : many(TopLevelDecl) token(EOF)71Root : RootExportDecl many(TopLevelDecl) token(EOF)
72
73RootExportDecl : token(Export) token(Symbol) token(String) token(Semicolon)
7074
71TopLevelDecl : FnDef | ExternBlock75TopLevelDecl : FnDef | ExternBlock
7276
doc/vim/syntax/zig.vim+15
...@@ -10,7 +10,22 @@ endif...@@ -10,7 +10,22 @@ endif
10syn keyword zigKeyword fn return mut const extern unreachable export pub10syn keyword zigKeyword fn return mut const extern unreachable export pub
11syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void11syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void
1212
13syn region zigCommentLine start="//" end="$" contains=zigTodo,@Spell
14syn region zigCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=zigTodo,@Spell
15syn region zigCommentBlock matchgroup=zigCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=zigTodo,zigCommentBlockNest,@Spell
16syn region zigCommentBlockDoc matchgroup=zigCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=zigTodo,zigCommentBlockDocNest,@Spell
17syn region zigCommentBlockNest matchgroup=zigCommentBlock start="/\*" end="\*/" contains=zigTodo,zigCommentBlockNest,@Spell contained transparent
18syn region zigCommentBlockDocNest matchgroup=zigCommentBlockDoc start="/\*" end="\*/" contains=zigTodo,zigCommentBlockDocNest,@Spell contained transparent
19
20syn keyword zigTodo contained TODO XXX
21
13let b:current_syntax = "zig"22let b:current_syntax = "zig"
1423
15hi def link zigKeyword Keyword24hi def link zigKeyword Keyword
16hi def link zigType Type25hi def link zigType Type
26hi def link zigCommentLine Comment
27hi def link zigCommentLineDoc SpecialComment
28hi def link zigCommentBlock zigCommentLine
29hi def link zigCommentBlockDoc zigCommentLineDoc
30hi def link zigTodo Todo
31
example/hello.zig+2
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1export executable "hello";
2
1#link("c")3#link("c")
2extern {4extern {
3 fn puts(s: *mut u8) -> i32;5 fn puts(s: *mut u8) -> i32;
example/math.zig created+6
...@@ -0,0 +1,6 @@
1export library "math";
2
3export 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,6 +75,8 @@ struct CodeGen {
75 ZigList<llvm::DIScope *> block_scopes;75 ZigList<llvm::DIScope *> block_scopes;
76 llvm::DIFile *di_file;76 llvm::DIFile *di_file;
77 ZigList<FnTableEntry *> fn_defs;77 ZigList<FnTableEntry *> fn_defs;
78 Buf *out_name;
79 OutType out_type;
78};80};
7981
80struct TypeNode {82struct TypeNode {
...@@ -103,6 +105,8 @@ CodeGen *create_codegen(AstNode *root, Buf *in_full_path) {...@@ -103,6 +105,8 @@ CodeGen *create_codegen(AstNode *root, Buf *in_full_path) {
103 g->is_static = false;105 g->is_static = false;
104 g->build_type = CodeGenBuildTypeDebug;106 g->build_type = CodeGenBuildTypeDebug;
105 g->strip_debug_symbols = false;107 g->strip_debug_symbols = false;
108 g->out_name = nullptr;
109 g->out_type = OutTypeUnknown;
106110
107 os_path_split(in_full_path, &g->in_dir, &g->in_file);111 os_path_split(in_full_path, &g->in_dir, &g->in_file);
108 return g;112 return g;
...@@ -120,6 +124,14 @@ void codegen_set_strip(CodeGen *g, bool strip) {...@@ -120,6 +124,14 @@ void codegen_set_strip(CodeGen *g, bool strip) {
120 g->strip_debug_symbols = strip;124 g->strip_debug_symbols = strip;
121}125}
122126
127void codegen_set_out_type(CodeGen *g, OutType out_type) {
128 g->out_type = out_type;
129}
130
131void codegen_set_out_name(CodeGen *g, Buf *out_name) {
132 g->out_name = out_name;
133}
134
123static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {135static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
124 g->errors.add_one();136 g->errors.add_one();
125 ErrorMsg *last_msg = &g->errors.last();137 ErrorMsg *last_msg = &g->errors.last();
...@@ -294,6 +306,7 @@ static void find_declarations(CodeGen *g, AstNode *node) {...@@ -294,6 +306,7 @@ static void find_declarations(CodeGen *g, AstNode *node) {
294 case NodeTypeBlock:306 case NodeTypeBlock:
295 case NodeTypeExpression:307 case NodeTypeExpression:
296 case NodeTypeFnCall:308 case NodeTypeFnCall:
309 case NodeTypeRootExportDecl:
297 zig_unreachable();310 zig_unreachable();
298 }311 }
299}312}
...@@ -355,15 +368,50 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {...@@ -355,15 +368,50 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
355static void analyze_node(CodeGen *g, AstNode *node) {368static void analyze_node(CodeGen *g, AstNode *node) {
356 switch (node->type) {369 switch (node->type) {
357 case NodeTypeRoot:370 case NodeTypeRoot:
358 // Iterate once over the top level declarations to build the function table371 {
359 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {372 AstNode *root_export_decl_node = node->data.root.root_export_decl;
360 AstNode *child = node->data.root.top_level_decls.at(i);373 if (root_export_decl_node) {
361 find_declarations(g, child);374 assert(root_export_decl_node->type == NodeTypeRootExportDecl);
362 }375 if (!g->out_name)
363 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {376 g->out_name = &root_export_decl_node->data.root_export_decl.name;
364 AstNode *child = node->data.root.top_level_decls.at(i);377
365 analyze_node(g, child);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 break;415 break;
368 case NodeTypeExternBlock:416 case NodeTypeExternBlock:
369 for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) {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,6 +722,7 @@ static void gen_block(CodeGen *g, AstNode *block_node, bool add_implicit_return)
674 case NodeTypeFnCall:722 case NodeTypeFnCall:
675 case NodeTypeExternBlock:723 case NodeTypeExternBlock:
676 case NodeTypeDirective:724 case NodeTypeDirective:
725 case NodeTypeRootExportDecl:
677 zig_unreachable();726 zig_unreachable();
678 }727 }
679 }728 }
...@@ -929,6 +978,15 @@ static Buf *get_dynamic_linker(CodeGen *g) {...@@ -929,6 +978,15 @@ static Buf *get_dynamic_linker(CodeGen *g) {
929 }978 }
930}979}
931980
981/*
982
983# static link into libfoo.a
984ar cq libfoo.a foo1.o foo2.o
985
986# dynamic link into libfoo.so
987gcc -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*/
932void code_gen_link(CodeGen *g, const char *out_file) {990void code_gen_link(CodeGen *g, const char *out_file) {
933 LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry();991 LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry();
934 LLVMInitializeCore(registry);992 LLVMInitializeCore(registry);
...@@ -937,6 +995,10 @@ void code_gen_link(CodeGen *g, const char *out_file) {...@@ -937,6 +995,10 @@ void code_gen_link(CodeGen *g, const char *out_file) {
937 LLVMZigInitializeLowerIntrinsicsPass(registry);995 LLVMZigInitializeLowerIntrinsicsPass(registry);
938 LLVMZigInitializeUnreachableBlockElimPass(registry);996 LLVMZigInitializeUnreachableBlockElimPass(registry);
939997
998 if (!out_file) {
999 out_file = buf_ptr(g->out_name);
1000 }
1001
940 Buf out_file_o = BUF_INIT;1002 Buf out_file_o = BUF_INIT;
941 buf_init_from_str(&out_file_o, out_file);1003 buf_init_from_str(&out_file_o, out_file);
942 buf_append_str(&out_file_o, ".o");1004 buf_append_str(&out_file_o, ".o");
src/codegen.hpp+10
...@@ -12,6 +12,14 @@...@@ -12,6 +12,14 @@
1212
13struct CodeGen;13struct CodeGen;
1414
15enum OutType {
16 OutTypeUnknown,
17 OutTypeExe,
18 OutTypeLib,
19 OutTypeObj,
20};
21
22
15struct ErrorMsg {23struct ErrorMsg {
16 int line_start;24 int line_start;
17 int column_start;25 int column_start;
...@@ -30,6 +38,8 @@ enum CodeGenBuildType {...@@ -30,6 +38,8 @@ enum CodeGenBuildType {
30void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);38void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);
31void codegen_set_is_static(CodeGen *codegen, bool is_static);39void codegen_set_is_static(CodeGen *codegen, bool is_static);
32void codegen_set_strip(CodeGen *codegen, bool strip);40void codegen_set_strip(CodeGen *codegen, bool strip);
41void codegen_set_out_type(CodeGen *codegen, OutType out_type);
42void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
3343
34void semantic_analyze(CodeGen *g);44void semantic_analyze(CodeGen *g);
3545
src/main.cpp+45-20
...@@ -28,18 +28,24 @@...@@ -28,18 +28,24 @@
28static int usage(const char *arg0) {28static int usage(const char *arg0) {
29 fprintf(stderr, "Usage: %s [command] [options] target\n"29 fprintf(stderr, "Usage: %s [command] [options] target\n"
30 "Commands:\n"30 "Commands:\n"
31 " build create an executable from target\n"31 " build create executable, object, or library from target\n"
32 "Options:\n"32 " version print version number and exit\n"
33 " --output output file\n"33 "Optional Options:\n"
34 " --version print version number and exit\n"34 " --release build with optimizations on and debug protection off\n"
35 " -Ipath add path to header include path\n"35 " --static output will be statically linked\n"
36 " --release build with optimizations on\n"36 " --strip exclude debug symbols\n"
37 " --strip exclude debug symbols\n"37 " --export [exe|lib|obj] override output type\n"
38 " --static build a static executable\n"38 " --name [name] override output name\n"
39 " --output [file] override destination path\n"
39 , arg0);40 , arg0);
40 return EXIT_FAILURE;41 return EXIT_FAILURE;
41}42}
4243
44static int version(void) {
45 printf("%s\n", ZIG_VERSION_STRING);
46 return EXIT_SUCCESS;
47}
48
43static Buf *fetch_file(FILE *f) {49static Buf *fetch_file(FILE *f) {
44 int fd = fileno(f);50 int fd = fileno(f);
45 struct stat st;51 struct stat st;
...@@ -58,12 +64,12 @@ static Buf *fetch_file(FILE *f) {...@@ -58,12 +64,12 @@ static Buf *fetch_file(FILE *f) {
58 return buf;64 return buf;
59}65}
6066
61static int build(const char *arg0, const char *in_file, const char *out_file,67static int build(const char *arg0, const char *in_file, const char *out_file, bool release,
62 ZigList<char *> *include_paths, bool release, bool strip, bool is_static)68 bool strip, bool is_static, OutType out_type, char *out_name)
63{69{
64 static char cur_dir[1024];70 static char cur_dir[1024];
6571
66 if (!in_file || !out_file)72 if (!in_file)
67 return usage(arg0);73 return usage(arg0);
6874
69 FILE *in_f;75 FILE *in_f;
...@@ -100,6 +106,10 @@ static int build(const char *arg0, const char *in_file, const char *out_file,...@@ -100,6 +106,10 @@ static int build(const char *arg0, const char *in_file, const char *out_file,
100 codegen_set_build_type(codegen, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);106 codegen_set_build_type(codegen, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
101 codegen_set_strip(codegen, strip);107 codegen_set_strip(codegen, strip);
102 codegen_set_is_static(codegen, is_static);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 semantic_analyze(codegen);113 semantic_analyze(codegen);
104 ZigList<ErrorMsg> *errors = codegen_error_messages(codegen);114 ZigList<ErrorMsg> *errors = codegen_error_messages(codegen);
105 if (errors->length == 0) {115 if (errors->length == 0) {
...@@ -135,25 +145,25 @@ static int build(const char *arg0, const char *in_file, const char *out_file,...@@ -135,25 +145,25 @@ static int build(const char *arg0, const char *in_file, const char *out_file,
135enum Cmd {145enum Cmd {
136 CmdNone,146 CmdNone,
137 CmdBuild,147 CmdBuild,
148 CmdVersion,
138};149};
139150
140int main(int argc, char **argv) {151int main(int argc, char **argv) {
141 char *arg0 = argv[0];152 char *arg0 = argv[0];
142 char *in_file = NULL;153 char *in_file = NULL;
143 char *out_file = NULL;154 char *out_file = NULL;
144 ZigList<char *> include_paths = {0};
145 bool release = false;155 bool release = false;
146 bool strip = false;156 bool strip = false;
147 bool is_static = false;157 bool is_static = false;
148158
159 OutType out_type = OutTypeUnknown;
160 char *out_name = NULL;
161
149 Cmd cmd = CmdNone;162 Cmd cmd = CmdNone;
150 for (int i = 1; i < argc; i += 1) {163 for (int i = 1; i < argc; i += 1) {
151 char *arg = argv[i];164 char *arg = argv[i];
152 if (arg[0] == '-' && arg[1] == '-') {165 if (arg[0] == '-' && arg[1] == '-') {
153 if (strcmp(arg, "--version") == 0) {166 if (strcmp(arg, "--release") == 0) {
154 printf("%s\n", ZIG_VERSION_STRING);
155 return EXIT_SUCCESS;
156 } else if (strcmp(arg, "--release") == 0) {
157 release = true;167 release = true;
158 } else if (strcmp(arg, "--strip") == 0) {168 } else if (strcmp(arg, "--strip") == 0) {
159 strip = true;169 strip = true;
...@@ -165,15 +175,27 @@ int main(int argc, char **argv) {...@@ -165,15 +175,27 @@ int main(int argc, char **argv) {
165 i += 1;175 i += 1;
166 if (strcmp(arg, "--output") == 0) {176 if (strcmp(arg, "--output") == 0) {
167 out_file = argv[i];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 } else {190 } else {
169 return usage(arg0);191 return usage(arg0);
170 }192 }
171 }193 }
172 } else if (arg[0] == '-' && arg[1] == 'I') {
173 include_paths.append(arg + 2);
174 } else if (cmd == CmdNone) {194 } else if (cmd == CmdNone) {
175 if (strcmp(arg, "build") == 0) {195 if (strcmp(arg, "build") == 0) {
176 cmd = CmdBuild;196 cmd = CmdBuild;
197 } else if (strcmp(arg, "version") == 0) {
198 cmd = CmdVersion;
177 } else {199 } else {
178 fprintf(stderr, "Unrecognized command: %s\n", arg);200 fprintf(stderr, "Unrecognized command: %s\n", arg);
179 return usage(arg0);201 return usage(arg0);
...@@ -189,6 +211,8 @@ int main(int argc, char **argv) {...@@ -189,6 +211,8 @@ int main(int argc, char **argv) {
189 return usage(arg0);211 return usage(arg0);
190 }212 }
191 break;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,9 +221,10 @@ int main(int argc, char **argv) {
197 case CmdNone:221 case CmdNone:
198 return usage(arg0);222 return usage(arg0);
199 case CmdBuild: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 }
202228
203 zig_unreachable();229 zig_unreachable();
204}230}
205
src/parser.cpp+40
...@@ -29,6 +29,8 @@ const char *node_type_str(NodeType node_type) {...@@ -29,6 +29,8 @@ const char *node_type_str(NodeType node_type) {
29 switch (node_type) {29 switch (node_type) {
30 case NodeTypeRoot:30 case NodeTypeRoot:
31 return "Root";31 return "Root";
32 case NodeTypeRootExportDecl:
33 return "RootExportDecl";
32 case NodeTypeFnDef:34 case NodeTypeFnDef:
33 return "FnDef";35 return "FnDef";
34 case NodeTypeFnDecl:36 case NodeTypeFnDecl:
...@@ -68,6 +70,11 @@ void ast_print(AstNode *node, int indent) {...@@ -68,6 +70,11 @@ void ast_print(AstNode *node, int indent) {
68 ast_print(child, indent + 2);70 ast_print(child, indent + 2);
69 }71 }
70 break;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 case NodeTypeFnDef:78 case NodeTypeFnDef:
72 {79 {
73 fprintf(stderr, "%s\n", node_type_str(node->type));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,6 +721,36 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
714 zig_unreachable();721 zig_unreachable();
715}722}
716723
724static 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/*
752Root : RootExportDecl many(TopLevelDecl) token(EOF)
753 */
717AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) {754AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) {
718 ParseContext pc = {0};755 ParseContext pc = {0};
719 pc.buf = buf;756 pc.buf = buf;
...@@ -721,6 +758,9 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) {...@@ -721,6 +758,9 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) {
721 pc.tokens = tokens;758 pc.tokens = tokens;
722759
723 int token_index = 0;760 int token_index = 0;
761
762 pc.root->data.root.root_export_decl = ast_parse_root_export_decl(&pc, &token_index);
763
724 ast_parse_top_level_decls(&pc, &token_index, &pc.root->data.root.top_level_decls);764 ast_parse_top_level_decls(&pc, &token_index, &pc.root->data.root.top_level_decls);
725765
726 if (token_index != tokens->length - 1) {766 if (token_index != tokens->length - 1) {
src/parser.hpp+8
...@@ -17,6 +17,7 @@ struct CodeGenNode;...@@ -17,6 +17,7 @@ struct CodeGenNode;
1717
18enum NodeType {18enum NodeType {
19 NodeTypeRoot,19 NodeTypeRoot,
20 NodeTypeRootExportDecl,
20 NodeTypeFnProto,21 NodeTypeFnProto,
21 NodeTypeFnDef,22 NodeTypeFnDef,
22 NodeTypeFnDecl,23 NodeTypeFnDecl,
...@@ -31,6 +32,7 @@ enum NodeType {...@@ -31,6 +32,7 @@ enum NodeType {
31};32};
3233
33struct AstNodeRoot {34struct AstNodeRoot {
35 AstNode *root_export_decl;
34 ZigList<AstNode *> top_level_decls;36 ZigList<AstNode *> top_level_decls;
35};37};
3638
...@@ -113,6 +115,11 @@ struct AstNodeDirective {...@@ -113,6 +115,11 @@ struct AstNodeDirective {
113 Buf param;115 Buf param;
114};116};
115117
118struct AstNodeRootExportDecl {
119 Buf type;
120 Buf name;
121};
122
116struct AstNode {123struct AstNode {
117 enum NodeType type;124 enum NodeType type;
118 AstNode *parent;125 AstNode *parent;
...@@ -121,6 +128,7 @@ struct AstNode {...@@ -121,6 +128,7 @@ struct AstNode {
121 CodeGenNode *codegen_node;128 CodeGenNode *codegen_node;
122 union {129 union {
123 AstNodeRoot root;130 AstNodeRoot root;
131 AstNodeRootExportDecl root_export_decl;
124 AstNodeFnDef fn_def;132 AstNodeFnDef fn_def;
125 AstNodeFnDecl fn_decl;133 AstNodeFnDecl fn_decl;
126 AstNodeFnProto fn_proto;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,6 +39,10 @@ static void add_simple_case(const char *case_name, const char *source, const cha
3939
40 test_case->compiler_args.append("build");40 test_case->compiler_args.append("build");
41 test_case->compiler_args.append(tmp_source_path);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 test_case->compiler_args.append("--output");46 test_case->compiler_args.append("--output");
43 test_case->compiler_args.append(tmp_exe_path);47 test_case->compiler_args.append(tmp_exe_path);
44 test_case->compiler_args.append("--release");48 test_case->compiler_args.append("--release");