diff --git a/examples/demo.odin b/examples/demo.odin index a3d43acae..3152ac5c5 100644 --- a/examples/demo.odin +++ b/examples/demo.odin @@ -664,6 +664,16 @@ named_proc_parameters :: proc() { fmt.println("foo2 =", foo2()); // 567 321 } + +enum_export :: proc() { + Foo :: enum #export {A, B, C}; + + f0 := A; + f1 := B; + f2 := C; + fmt.println(f0, f1, f2); +} + main :: proc() { when true { general_stuff(); @@ -674,6 +684,7 @@ main :: proc() { array_programming(); using_in(); named_proc_parameters(); + enum_export(); } } diff --git a/src/check_type.cpp b/src/check_type.cpp index e41670bd3..41c975185 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -796,6 +796,21 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod enum_type->Enum.fields = fields.data; enum_type->Enum.field_count = cast(i32)fields.count; + enum_type->Enum.is_export = et->is_export; + if (et->is_export) { + Scope *parent = c->context.scope->parent; + for_array(i, fields) { + Entity *f = fields[i]; + if (f->kind != Entity_Constant) { + continue; + } + String name = f->token.string; + if (is_blank_ident(name)) { + continue; + } + add_entity(c, parent, nullptr, f); + } + } enum_type->Enum.count = make_entity_constant(c->allocator, c->context.scope, make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count)); diff --git a/src/main.cpp b/src/main.cpp index be5dd4669..1f2ffd17c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -723,7 +723,7 @@ int main(int arg_count, char **arg_ptr) { #if defined(GB_SYSTEM_WINDOWS) // For more passes arguments: http://llvm.org/docs/Passes.html exit_code = system_exec_command_line_app("llvm-opt", false, - "\"%.*sbin/opt\" \"%.*s\".ll -o \"%.*s\".bc %.*s " + "\"%.*sbin/opt\" \"%.*s.ll\" -o \"%.*s.bc\" %.*s " "-mem2reg " "-memcpyopt " "-die " @@ -731,6 +731,11 @@ int main(int arg_count, char **arg_ptr) { LIT(build_context.ODIN_ROOT), LIT(output_base), LIT(output_base), LIT(build_context.opt_flags)); + // exit_code = system_exec_command_line_app("llvm-opt", false, + // "\"%.*sbin/llvm-as\" \"%.*s.ll\" -o \"%.*s.bc\" " + // "", + // LIT(build_context.ODIN_ROOT), + // LIT(output_base), LIT(output_base)); if (exit_code != 0) { return exit_code; } @@ -738,7 +743,7 @@ int main(int arg_count, char **arg_ptr) { // NOTE(zangent): This is separate because it seems that LLVM tools are packaged // with the Windows version, while they will be system-provided on MacOS and GNU/Linux exit_code = system_exec_command_line_app("llvm-opt", false, - "opt \"%.*s.ll\" -o \"%.*s\".bc %.*s " + "opt \"%.*s.ll\" -o \"%.*s.bc\" %.*s " "-mem2reg " "-memcpyopt " "-die " diff --git a/src/parser.cpp b/src/parser.cpp index 1c03af2e3..de246243a 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -947,10 +947,11 @@ AstNode *ast_union_type(AstFile *f, Token token, Array variants, AstN } -AstNode *ast_enum_type(AstFile *f, Token token, AstNode *base_type, Array fields) { +AstNode *ast_enum_type(AstFile *f, Token token, AstNode *base_type, bool is_export, Array fields) { AstNode *result = make_ast_node(f, AstNode_EnumType); result->EnumType.token = token; result->EnumType.base_type = base_type; + result->EnumType.is_export = is_export; result->EnumType.fields = fields; return result; } @@ -1933,17 +1934,36 @@ AstNode *parse_operand(AstFile *f, bool lhs) { } break; case Token_enum: { + bool is_export = false; Token token = expect_token(f, Token_enum); AstNode *base_type = nullptr; if (f->curr_token.kind != Token_OpenBrace) { - base_type = parse_type(f); + if (f->curr_token.kind != Token_Hash) { + base_type = parse_type(f); + } + while (allow_token(f, Token_Hash)) { + Token tag = f->curr_token; + if (f->curr_token.kind != Token_Ident && f->curr_token.kind != Token_export) { + expect_token_after(f, Token_Ident, "#"); + } else { + tag = advance_token(f); + } + if (tag.string == "export") { + if (is_export) { + syntax_error(tag, "Duplicate enum tag '#%.*s'", LIT(tag.string)); + } + is_export = true; + } else { + syntax_error(tag, "Invalid enum tag '#%.*s'", LIT(tag.string)); + } + } } Token open = expect_token(f, Token_OpenBrace); Array values = parse_element_list(f); Token close = expect_token(f, Token_CloseBrace); - return ast_enum_type(f, token, base_type, values); + return ast_enum_type(f, token, base_type, is_export, values); } break; case Token_bit_field: { diff --git a/src/parser.hpp b/src/parser.hpp index f73afe40a..f9a520e40 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -469,6 +469,7 @@ AST_NODE_KIND(_TypeBegin, "", i32) \ AST_NODE_KIND(EnumType, "enum type", struct { \ Token token; \ AstNode * base_type; \ + bool is_export; \ Array fields; /* FieldValue */ \ }) \ AST_NODE_KIND(BitFieldType, "bit field type", struct { \ diff --git a/src/types.cpp b/src/types.cpp index f089351e4..c40c076f1 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -132,6 +132,7 @@ struct TypeStruct { Scope * scope; \ Entity * names; \ Type * base_type; \ + bool is_export; \ Entity * count; \ Entity * min_value; \ Entity * max_value; \