typedef struct AstArrayType AstArrayType;
typedef struct AstStructType AstStructType;
typedef struct AstStructMember AstStructMember;
+typedef struct AstEnumType AstEnumType;
+typedef struct AstEnumValue AstEnumValue;
typedef struct AstBinding AstBinding;
typedef struct AstIncludeFile AstIncludeFile;
Ast_Kind_Function_Type,
Ast_Kind_Array_Type,
Ast_Kind_Struct_Type,
+ Ast_Kind_Enum_Type,
Ast_Kind_Type_End,
Ast_Kind_Struct_Member,
+ Ast_Kind_Enum_Value,
Ast_Kind_NumLit,
Ast_Kind_StrLit,
Type *stcache;
};
struct AstStructMember { AstTyped_base; u64 offset; };
+struct AstEnumType {
+ AstType_base;
+ Scope *scope;
+
+ AstType *backing;
+ Type *backing_type;
+
+ bh_arr(AstEnumValue *) values;
+
+ // NOTE: Used to cache the actual type for the same reason as above.
+ Type *etcache;
+};
+struct AstEnumValue { AstTyped_base; AstNumLit* value; };
// Top level nodes
struct AstBinding { AstTyped_base; AstNode* node; };
Package* package;
};
-
// NOTE: An Entity represents something will need to be
// processed later down the pipeline.
typedef enum EntityType {
Entity_Type_Unknown,
Entity_Type_Use_Package,
Entity_Type_String_Literal,
+ Entity_Type_Enum,
Entity_Type_Struct,
Entity_Type_Function_Header,
Entity_Type_Global_Header,
AstTyped *expr;
AstStrLit *strlit;
AstStructType *struct_type;
+ AstEnumType *enum_type;
};
} Entity;
} StructMember;
#define TYPE_KINDS \
- TYPE_KIND(Basic, TypeBasic) \
- TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \
- TYPE_KIND(Function, struct { \
- Type *return_type; \
- u64 param_count; \
- Type* params[]; \
- }) \
- TYPE_KIND(Struct, struct { \
- char* name; \
- u32 size; \
- u32 mem_count; \
- bh_table(StructMember) members; \
- bh_arr(StructMember *) memarr; \
- }) \
- TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; })
+ TYPE_KIND(Basic, TypeBasic) \
+ TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \
+ TYPE_KIND(Function, struct { \
+ Type *return_type; \
+ u64 param_count; \
+ Type* params[]; \
+ }) \
+ TYPE_KIND(Struct, struct { \
+ char* name; \
+ u32 size; \
+ u32 mem_count; \
+ bh_table(StructMember) members; \
+ bh_arr(StructMember *) memarr; \
+ }) \
+ TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) \
+ TYPE_KIND(Enum, struct { char* name; Type* backing; })
typedef enum TypeKind {
Type_Kind_Invalid,
use "progs/print_funcs"
-use package printing as p {
- print_f32, PrintableArray
-}
+use package printing
Foo :: struct {
x : i32;
y : i32;
+
+ st : SomeType;
}
foo_sum :: proc (foo: ^Foo) -> i32 {
}
asdf :: proc (pa: PrintableArray) {
- for i: 0, pa.len p.print(pa.data[i] as i32);
+ for i: 0, pa.len print(pa.data[i] as i32);
+}
+
+SomeType :: enum (u16) {
+ Value1;
+ Value2;
+ Value3 = 80;
+ Value4;
+}
+
+print_st :: proc (st: SomeType) {
+ print(st as i32);
}
proc #export "main" {
+
+ st := SomeType.Value4;
+ print_st(st);
+
foo := __heap_start as ^Foo;
foo.x = 123;
foo.y = 321;
- p.print(foo.foo_sum());
+ foo.st = st;
+ print(sizeof Foo);
+ print(foo.foo_sum());
+ print_st(foo.st);
- pa := (__heap_start as i32 + 8) as ^p.PrintableArray;
+ pa := (__heap_start as i32 + sizeof Foo) as ^PrintableArray;
pa.data = __heap_start as ^u8;
pa.len = 5;
asdf(*pa);
- p.print(1234);
+ print(1234);
print_f32(123.0f);
}
break;
}
+ case Ast_Kind_Enum_Type: {
+ ent.type = Entity_Type_Enum;
+ ent.enum_type = (AstEnumType *) node;
+ bh_arr_push(compiler_state->prog_info.entities, ent);
+ break;
+ }
+
case Ast_Kind_Use_Package: {
ent.type = Entity_Type_Use_Package;
ent.use_package = (AstUsePackage *) node;
case Ast_Kind_StrLit: break;
case Ast_Kind_Function: break;
case Ast_Kind_Overloaded_Function: break;
+ case Ast_Kind_Enum_Value: break;
default:
retval = 1;
if (check_struct(entity->struct_type)) return;
break;
+ case Entity_Type_Enum: break;
+
case Entity_Type_String_Literal: break;
case Entity_Type_Global_Header: break;
static AstLocal* parse_function_params(OnyxParser* parser);
static AstFunction* parse_function_definition(OnyxParser* parser);
static AstTyped* parse_global_declaration(OnyxParser* parser);
+static AstEnumType* parse_enum_declaration(OnyxParser* parser);
static AstTyped* parse_top_level_expression(OnyxParser* parser);
static AstNode* parse_top_level_statement(OnyxParser* parser);
return (AstTyped *) global_node;
}
+static AstEnumType* parse_enum_declaration(OnyxParser* parser) {
+ AstEnumType* enum_node = make_node(AstEnumType, Ast_Kind_Enum_Type);
+ enum_node->token = expect_token(parser, Token_Type_Keyword_Enum);
+
+ bh_arr_new(global_heap_allocator, enum_node->values, 4);
+
+ AstType* backing = (AstType *) &basic_type_u32;
+ if (parser->curr->type == '(') {
+ consume_token(parser);
+
+ AstNode* backing_sym = make_node(AstNode, Ast_Kind_Symbol);
+ backing_sym->token = expect_token(parser, Token_Type_Symbol);
+ backing = (AstType *) backing_sym;
+
+ expect_token(parser, ')');
+ }
+ enum_node->backing = backing;
+
+ expect_token(parser, '{');
+
+ while (parser->curr->type != '}') {
+ AstEnumValue* evalue = make_node(AstEnumValue, Ast_Kind_Enum_Value);
+ evalue->token = expect_token(parser, Token_Type_Symbol);
+ evalue->type_node = (AstType *) enum_node;
+
+ if (parser->curr->type == '=') {
+ consume_token(parser);
+ evalue->value = parse_numeric_literal(parser);
+ }
+
+ expect_token(parser, ';');
+
+ bh_arr_push(enum_node->values, evalue);
+ }
+
+ expect_token(parser, '}');
+
+ return enum_node;
+}
+
// <proc>
// <global>
// <expr>
return (AstTyped *) parse_struct(parser);
}
else if (parser->curr->type == Token_Type_Keyword_Enum) {
- consume_token(parser);
- return (AstTyped *) &error_node;
+ return (AstTyped *) parse_enum_declaration(parser);
}
else {
return parse_expression(parser);
} else if (node->kind != Ast_Kind_Overloaded_Function
&& node->kind != Ast_Kind_StrLit) {
- if (node->kind == Ast_Kind_Struct_Type) {
+ if (node->kind == Ast_Kind_Struct_Type || node->kind == Ast_Kind_Enum_Type) {
((AstStructType *)node)->name = bh_aprintf(global_heap_allocator,
"%b", symbol->text, symbol->length);
}
static void symres_global(AstGlobal* global);
static void symres_overloaded_function(AstOverloadedFunction* ofunc);
static void symres_use_package(AstUsePackage* package);
+static void symres_enum(AstEnumType* enum_node);
static void scope_enter(Scope* new_scope) {
if (new_scope->parent == NULL)
if (n) {
// NOTE: not field access
*fa = (AstFieldAccess *) n;
+ return;
+ }
+ }
+
+ if ((*fa)->expr->kind == Ast_Kind_Enum_Type) {
+ AstEnumType* etype = (AstEnumType *) (*fa)->expr;
+ AstNode* n = symbol_resolve(etype->scope, (*fa)->token);
+ if (n) {
+ // NOTE: not field access
+ *fa = (AstFieldAccess *) n;
+ return;
}
}
}
scope_include(semstate.curr_package->include_scope, p->scope);
}
+static void symres_enum(AstEnumType* enum_node) {
+ if (enum_node->backing->kind == Ast_Kind_Symbol) {
+ enum_node->backing = (AstType *) symbol_resolve(semstate.curr_scope, enum_node->backing->token);
+ }
+ if (enum_node->backing == NULL) return;
+
+ enum_node->backing_type = type_build_from_ast(semstate.allocator, enum_node->backing);
+ enum_node->scope = scope_create(semstate.node_allocator, NULL);
+
+ u64 next_assign_value = 0;
+ bh_arr_each(AstEnumValue *, value, enum_node->values) {
+ symbol_introduce(enum_node->scope, (*value)->token, (AstNode *) *value);
+
+ if ((*value)->value != NULL) {
+ // HACK
+ if ((*value)->value->type_node == (AstType *) &basic_type_i32) {
+ next_assign_value = (*value)->value->value.i;
+ } else if ((*value)->value->type_node == (AstType *) &basic_type_i64) {
+ next_assign_value = (*value)->value->value.l;
+ } else {
+ onyx_message_add(Msg_Type_Literal,
+ (*value)->value->token->pos,
+ "expected numeric integer literal for enum initialization");
+ return;
+ }
+
+ } else {
+ AstNumLit* num = onyx_ast_node_new(semstate.node_allocator, sizeof(AstNumLit), Ast_Kind_NumLit);
+ num->value.l = next_assign_value;
+ num->type_node = enum_node->backing;
+ num->type = enum_node->backing_type;
+ (*value)->value = num;
+ }
+
+ next_assign_value++;
+ }
+}
+
void onyx_resolve_symbols() {
semstate.curr_scope = semstate.program->global_scope;
case Entity_Type_Global: symres_global(entity->global); break;
case Entity_Type_Expression: symres_expression(&entity->expr); break;
case Entity_Type_Struct: symres_type((AstType *) entity->struct_type); break;
+ case Entity_Type_Enum: symres_enum(entity->enum_type); break;
default: break;
}
return works;
}
+ case Type_Kind_Enum: {
+ if (t2->kind != Type_Kind_Enum) return 0;
+ return t1 == t2;
+ }
+
default:
assert(("Invalid type", 0));
break;
return works;
}
+ case Type_Kind_Enum: {
+ if (t2->kind != Type_Kind_Enum) return 0;
+ return t1 == t2;
+ }
+
default:
assert(("Invalid type", 0));
break;
case Type_Kind_Function: return 0;
case Type_Kind_Array: return type->Array.size;
case Type_Kind_Struct: return type->Struct.size;
+ case Type_Kind_Enum: return type_size_of(type->Enum.backing);
default: return 0;
}
}
return s_type;
}
+ case Ast_Kind_Enum_Type: {
+ AstEnumType* enum_node = (AstEnumType *) type_node;
+ if (enum_node->etcache) return enum_node->etcache;
+
+ Type* enum_type = bh_alloc(alloc, sizeof(Type));
+ enum_node->etcache = enum_type;
+
+ enum_type->kind = Type_Kind_Enum;
+ enum_type->Enum.backing = enum_node->backing_type;
+ enum_type->Enum.name = enum_node->name;
+
+ return enum_type;
+ }
+
case Ast_Kind_Basic_Type:
return ((AstBasicType *) type_node)->type;
return type->Struct.name;
else
return "<anonymous struct>";
+ case Type_Kind_Enum:
+ if (type->Enum.name)
+ return type->Enum.name;
+ else
+ return "<anonymous enum>";
default: return "unknown";
}
}
"FUNCTION_TYPE",
"ARRAY TYPE",
"STRUCT TYPE",
+ "ENUM TYPE"
"TYPE_END (BAD)",
"STRUCT MEMBER",
+ "ENUM VALUE",
"NUMERIC LITERAL",
"STRING LITERAL",
DEBUG_HERE;
}
+ if (type->kind == Type_Kind_Enum) {
+ return onyx_type_to_wasm_type(type->Enum.backing);
+ }
+
if (type->kind == Type_Kind_Pointer) {
return WASM_TYPE_INT32;
}
COMPILE_FUNC(store_instruction, Type* type, u32 alignment, u32 offset) {
bh_arr(WasmInstruction) code = *pcode;
+ if (type->kind == Type_Kind_Enum) {
+ type = type->Enum.backing;
+ }
+
i32 store_size = type_size_of(type);
- i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
+ i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
i32 is_pointer = is_basic && (type->Basic.flags & Basic_Flag_Pointer);
i32 is_integer = is_basic && (type->Basic.flags & Basic_Flag_Integer);
i32 is_float = is_basic && type->Basic.flags & Basic_Flag_Float;
COMPILE_FUNC(load_instruction, Type* type, u32 offset) {
bh_arr(WasmInstruction) code = *pcode;
+
+ if (type->kind == Type_Kind_Enum) {
+ type = type->Enum.backing;
+ }
i32 load_size = type_size_of(type);
i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
break;
}
+ case Ast_Kind_Enum_Value: {
+ AstEnumValue* ev = (AstEnumValue *) expr;
+ WasmType backing_type = onyx_type_to_wasm_type(ev->type);
+ if (backing_type == WASM_TYPE_INT32) {
+ WID(WI_I32_CONST, ev->value->value.i);
+ }
+ else if (backing_type == WASM_TYPE_INT64) {
+ WID(WI_I64_CONST, ev->value->value.l);
+ }
+ else {
+ onyx_message_add(Msg_Type_Literal,
+ ev->token->pos,
+ "invalid backing type for enum");
+ }
+ break;
+ }
+
default:
bh_printf("Unhandled case: %d\n", expr->kind);
DEBUG_HERE;