Browse Source

`enum #export`

gingerBill 7 years ago
parent
commit
88ba6d8015
6 changed files with 58 additions and 5 deletions
  1. 11 0
      examples/demo.odin
  2. 15 0
      src/check_type.cpp
  3. 7 2
      src/main.cpp
  4. 23 3
      src/parser.cpp
  5. 1 0
      src/parser.hpp
  6. 1 0
      src/types.cpp

+ 11 - 0
examples/demo.odin

@@ -664,6 +664,16 @@ named_proc_parameters :: proc() {
 	fmt.println("foo2 =", foo2()); // 567 321
 	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() {
 main :: proc() {
 	when true {
 	when true {
 		general_stuff();
 		general_stuff();
@@ -674,6 +684,7 @@ main :: proc() {
 		array_programming();
 		array_programming();
 		using_in();
 		using_in();
 		named_proc_parameters();
 		named_proc_parameters();
+		enum_export();
 	}
 	}
 }
 }
 
 

+ 15 - 0
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.fields      = fields.data;
 	enum_type->Enum.field_count = cast(i32)fields.count;
 	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,
 	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));
 		make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count));

+ 7 - 2
src/main.cpp

@@ -723,7 +723,7 @@ int main(int arg_count, char **arg_ptr) {
 	#if defined(GB_SYSTEM_WINDOWS)
 	#if defined(GB_SYSTEM_WINDOWS)
 		// For more passes arguments: http://llvm.org/docs/Passes.html
 		// For more passes arguments: http://llvm.org/docs/Passes.html
 		exit_code = system_exec_command_line_app("llvm-opt", false,
 		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 "
 			"-mem2reg "
 			"-memcpyopt "
 			"-memcpyopt "
 			"-die "
 			"-die "
@@ -731,6 +731,11 @@ int main(int arg_count, char **arg_ptr) {
 			LIT(build_context.ODIN_ROOT),
 			LIT(build_context.ODIN_ROOT),
 			LIT(output_base), LIT(output_base),
 			LIT(output_base), LIT(output_base),
 			LIT(build_context.opt_flags));
 			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) {
 		if (exit_code != 0) {
 			return exit_code;
 			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
 		// 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
 		//   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,
 		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 "
 			"-mem2reg "
 			"-memcpyopt "
 			"-memcpyopt "
 			"-die "
 			"-die "

+ 23 - 3
src/parser.cpp

@@ -947,10 +947,11 @@ AstNode *ast_union_type(AstFile *f, Token token, Array<AstNode *> variants, AstN
 }
 }
 
 
 
 
-AstNode *ast_enum_type(AstFile *f, Token token, AstNode *base_type, Array<AstNode *> fields) {
+AstNode *ast_enum_type(AstFile *f, Token token, AstNode *base_type, bool is_export, Array<AstNode *> fields) {
 	AstNode *result = make_ast_node(f, AstNode_EnumType);
 	AstNode *result = make_ast_node(f, AstNode_EnumType);
 	result->EnumType.token = token;
 	result->EnumType.token = token;
 	result->EnumType.base_type = base_type;
 	result->EnumType.base_type = base_type;
+	result->EnumType.is_export = is_export;
 	result->EnumType.fields = fields;
 	result->EnumType.fields = fields;
 	return result;
 	return result;
 }
 }
@@ -1933,17 +1934,36 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 	} break;
 	} break;
 
 
 	case Token_enum: {
 	case Token_enum: {
+		bool is_export = false;
 		Token token = expect_token(f, Token_enum);
 		Token token = expect_token(f, Token_enum);
 		AstNode *base_type = nullptr;
 		AstNode *base_type = nullptr;
 		if (f->curr_token.kind != Token_OpenBrace) {
 		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);
 		Token open = expect_token(f, Token_OpenBrace);
 
 
 		Array<AstNode *> values = parse_element_list(f);
 		Array<AstNode *> values = parse_element_list(f);
 		Token close = expect_token(f, Token_CloseBrace);
 		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;
 	} break;
 
 
 	case Token_bit_field: {
 	case Token_bit_field: {

+ 1 - 0
src/parser.hpp

@@ -469,6 +469,7 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
 	AST_NODE_KIND(EnumType, "enum type", struct { \
 	AST_NODE_KIND(EnumType, "enum type", struct { \
 		Token            token; \
 		Token            token; \
 		AstNode *        base_type; \
 		AstNode *        base_type; \
+		bool             is_export; \
 		Array<AstNode *> fields; /* FieldValue */ \
 		Array<AstNode *> fields; /* FieldValue */ \
 	}) \
 	}) \
 	AST_NODE_KIND(BitFieldType, "bit field type", struct { \
 	AST_NODE_KIND(BitFieldType, "bit field type", struct { \

+ 1 - 0
src/types.cpp

@@ -132,6 +132,7 @@ struct TypeStruct {
 		Scope *  scope;                                   \
 		Scope *  scope;                                   \
 		Entity * names;                                   \
 		Entity * names;                                   \
 		Type *   base_type;                               \
 		Type *   base_type;                               \
+		bool     is_export;                               \
 		Entity * count;                                   \
 		Entity * count;                                   \
 		Entity * min_value;                               \
 		Entity * min_value;                               \
 		Entity * max_value;                               \
 		Entity * max_value;                               \