From: Brendan Hansen Date: Fri, 29 Jan 2021 15:19:37 +0000 (-0600) Subject: structures can have statically bound expressions in their scope X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8b5d4e88fe5726253f366733ffc3cd4a26790d82;p=onyx.git structures can have statically bound expressions in their scope --- diff --git a/bin/onyx b/bin/onyx index 73509c3b..6198097d 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 2ed97444..c4e9d065 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -641,6 +641,9 @@ struct AstStructType { // a struct type is kind of complicated and should // only happen once. Type *stcache; + + // NOTE: Used to store statically bound expressions in the struct. + Scope* scope; }; struct AstStructMember { AstTyped_base; @@ -999,6 +1002,15 @@ extern AstBasicType basic_type_rawptr; extern AstBasicType basic_type_int_unsized; extern AstBasicType basic_type_float_unsized; +extern AstBasicType basic_type_i8x16; +extern AstBasicType basic_type_i16x8; +extern AstBasicType basic_type_i32x4; +extern AstBasicType basic_type_i64x2; +extern AstBasicType basic_type_f32x4; +extern AstBasicType basic_type_f64x2; +extern AstBasicType basic_type_v128; + + // :TypeExprHack extern AstNode type_expr_symbol; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index d34277d3..daa6d7b0 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -137,6 +137,11 @@ struct Type { TypeKind kind; u32 flags; + + // NOTE(Brendan Hansen): The abstract syntax tree node used to create + // the type. Primarily used to look up symbols in scopes that are embedded + // in the type. + struct AstType* ast_type; union { #define TYPE_KIND(k, ...) Type##k k; diff --git a/onyx.exe b/onyx.exe index 13c200b9..872f78ca 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 3ec011bb..c825d36f 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -1314,12 +1314,23 @@ CheckStatus check_field_access(AstFieldAccess** pfield) { } if (!type_lookup_member(field->expr->type, field->field, &smem)) { - onyx_report_error(field->token->pos, - "Field '%s' does not exists on '%s'.", - field->field, - node_get_type_name(field->expr)); - - return Check_Error; + AstStructType* struct_node = (AstStructType *) field->expr->type->ast_type; + assert(struct_node); + assert(struct_node->kind == Ast_Kind_Struct_Type); + + AstNode* n = symbol_raw_resolve(struct_node->scope, field->field); + if (n) { + *pfield = (AstFieldAccess *) n; + return Check_Success; + + } else { + onyx_report_error(field->token->pos, + "Field '%s' does not exists on '%s'.", + field->field, + node_get_type_name(field->expr)); + + return Check_Error; + } } field->offset = smem.offset; diff --git a/src/onyxparser.c b/src/onyxparser.c index 7f3b6a67..3534177f 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1829,31 +1829,53 @@ static AstStructType* parse_struct(OnyxParser* parser) { } expect_token(parser, '{'); + b32 member_is_used = 0; while (parser->curr->type != '}') { if (parser->hit_unexpected_token) return s_node; - - AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member); + + OnyxToken* member_name; if (parser->curr->type == Token_Type_Keyword_Use) { consume_token(parser); - mem->flags |= Ast_Flag_Struct_Mem_Used; + member_is_used = 1; } - mem->token = expect_token(parser, Token_Type_Symbol); + member_name = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); - if (parser->curr->type != '=') { - mem->type_node = parse_type(parser); - } - - if (parser->curr->type == '=') { + + if (parser->curr->type == ':' && !member_is_used) { consume_token(parser); - mem->initial_value = parse_expression(parser, 0); - } - - expect_token(parser, ';'); + + if (!s_node->scope) { + // NOTE: The parent scope will be filled out during symbol resolution. + s_node->scope = scope_create(context.ast_alloc, NULL, s_node->token->pos); + } + + AstTyped* expression = parse_top_level_expression(parser); + symbol_introduce(s_node->scope, member_name, (AstNode *) expression); + + } else { + AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member); + mem->token = member_name; + + if (member_is_used) { + mem->flags |= Ast_Flag_Struct_Mem_Used; + member_is_used = 0; + } + + if (parser->curr->type != '=') { + mem->type_node = parse_type(parser); + } - bh_arr_push(s_node->members, mem); + if (parser->curr->type == '=') { + consume_token(parser); + mem->initial_value = parse_expression(parser, 0); + } + + expect_token(parser, ';'); + bh_arr_push(s_node->members, mem); + } } expect_token(parser, '}'); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 54d480b7..ce4b59fb 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -95,6 +95,9 @@ AstType* symres_type(AstType* type) { s_node->flags |= Ast_Flag_Type_Is_Resolved; + // FIX: This is probably wrong for the long term. + if (s_node->scope) s_node->scope->parent = curr_scope; + { bh_table(i32) mem_set; bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members)); @@ -296,6 +299,16 @@ static void symres_field_access(AstFieldAccess** fa) { return; } } + + if ((*fa)->expr->kind == Ast_Kind_Struct_Type) { + AstStructType* stype = (AstStructType *) (*fa)->expr; + AstNode* n = symbol_resolve(stype->scope, (*fa)->token); + if (n) { + // Note: not field access + *fa = (AstFieldAccess *) n; + return; + } + } } static void symres_compound(AstCompound* compound) { @@ -880,11 +893,15 @@ static void symres_struct_defaults(AstType* t) { if (t->kind != Ast_Kind_Struct_Type) return; AstStructType* st = (AstStructType *) t; + if (st->scope) scope_enter(st->scope); + bh_arr_each(AstStructMember *, smem, st->members) { if ((*smem)->initial_value != NULL) { symres_expression(&(*smem)->initial_value); } } + + if (st->scope) scope_leave(); } static void symres_polyproc(AstPolyProc* pp) { diff --git a/src/onyxtypes.c b/src/onyxtypes.c index efa806cf..94ff6094 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -8,33 +8,33 @@ static u32 next_unique_id = 1; // NOTE: These have to be in the same order as Basic Type basic_types[] = { - { Type_Kind_Basic, 0, { Basic_Kind_Void, 0, 0, 1, "void" } }, - - { Type_Kind_Basic, 0, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, 1, "bool" } }, - - { Type_Kind_Basic, 0, { Basic_Kind_Int_Unsized, Basic_Flag_Integer, 0, 0, "unsized int" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I8, Basic_Flag_Integer, 1, 1, "i8" } }, - { Type_Kind_Basic, 0, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, 1, "u8" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I16, Basic_Flag_Integer, 2, 2, "i16" } }, - { Type_Kind_Basic, 0, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, 2, "u16" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I32, Basic_Flag_Integer, 4, 4, "i32" } }, - { Type_Kind_Basic, 0, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, 4, "u32" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I64, Basic_Flag_Integer, 8, 8, "i64" } }, - { Type_Kind_Basic, 0, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, 8, "u64" } }, - - { Type_Kind_Basic, 0, { Basic_Kind_Float_Unsized, Basic_Flag_Float, 0, 0, "unsized float" } }, - { Type_Kind_Basic, 0, { Basic_Kind_F32, Basic_Flag_Float, 4, 4, "f32" } }, - { Type_Kind_Basic, 0, { Basic_Kind_F64, Basic_Flag_Float, 8, 4, "f64" } }, - - { Type_Kind_Basic, 0, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 8, 8, "rawptr" } }, - - { Type_Kind_Basic, 0, { Basic_Kind_I8X16, Basic_Flag_SIMD, 16, 16, "i8x16" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I16X8, Basic_Flag_SIMD, 16, 16, "i16x8" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I32X4, Basic_Flag_SIMD, 16, 16, "i32x4" } }, - { Type_Kind_Basic, 0, { Basic_Kind_I64X2, Basic_Flag_SIMD, 16, 16, "i64x2" } }, - { Type_Kind_Basic, 0, { Basic_Kind_F32X4, Basic_Flag_SIMD, 16, 16, "f32x4" } }, - { Type_Kind_Basic, 0, { Basic_Kind_F64X2, Basic_Flag_SIMD, 16, 16, "f64x2" } }, - { Type_Kind_Basic, 0, { Basic_Kind_V128, Basic_Flag_SIMD, 16, 16, "v128" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_void, { Basic_Kind_Void, 0, 0, 1, "void" } }, + + { Type_Kind_Basic, 0, (AstType *) &basic_type_bool, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, 1, "bool" } }, + + { Type_Kind_Basic, 0, NULL, { Basic_Kind_Int_Unsized, Basic_Flag_Integer, 0, 0, "unsized int" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i8, { Basic_Kind_I8, Basic_Flag_Integer, 1, 1, "i8" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_u8, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, 1, "u8" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i16, { Basic_Kind_I16, Basic_Flag_Integer, 2, 2, "i16" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_u16, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, 2, "u16" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i32, { Basic_Kind_I32, Basic_Flag_Integer, 4, 4, "i32" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_u32, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, 4, "u32" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i64, { Basic_Kind_I64, Basic_Flag_Integer, 8, 8, "i64" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_u64, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, 8, "u64" } }, + + { Type_Kind_Basic, 0, NULL, { Basic_Kind_Float_Unsized, Basic_Flag_Float, 0, 0, "unsized float" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_f32, { Basic_Kind_F32, Basic_Flag_Float, 4, 4, "f32" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_f64, { Basic_Kind_F64, Basic_Flag_Float, 8, 4, "f64" } }, + + { Type_Kind_Basic, 0, (AstType *) &basic_type_rawptr, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 8, 8, "rawptr" } }, + + { Type_Kind_Basic, 0, (AstType *) &basic_type_i8x16, { Basic_Kind_I8X16, Basic_Flag_SIMD, 16, 16, "i8x16" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i16x8, { Basic_Kind_I16X8, Basic_Flag_SIMD, 16, 16, "i16x8" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i32x4, { Basic_Kind_I32X4, Basic_Flag_SIMD, 16, 16, "i32x4" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_i64x2, { Basic_Kind_I64X2, Basic_Flag_SIMD, 16, 16, "i64x2" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_f32x4, { Basic_Kind_F32X4, Basic_Flag_SIMD, 16, 16, "f32x4" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_f64x2, { Basic_Kind_F64X2, Basic_Flag_SIMD, 16, 16, "f64x2" } }, + { Type_Kind_Basic, 0, (AstType *) &basic_type_v128, { Basic_Kind_V128, Basic_Flag_SIMD, 16, 16, "v128" } }, }; b32 types_are_surface_compatible(Type* t1, Type* t2) { @@ -300,7 +300,9 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { switch (type_node->kind) { case Ast_Kind_Pointer_Type: { - return type_make_pointer(alloc, type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem)); + Type* ptr_type = type_make_pointer(alloc, type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem)); + ptr_type->ast_type = type_node; + return ptr_type; } case Ast_Kind_Function_Type: { @@ -310,6 +312,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count); func_type->kind = Type_Kind_Function; + func_type->ast_type = type_node; func_type->Function.param_count = param_count; func_type->Function.needed_param_count = param_count; func_type->Function.return_type = type_build_from_ast(alloc, ftype_node->return_type); @@ -327,6 +330,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { Type* a_type = bh_alloc(alloc, sizeof(Type)); a_type->kind = Type_Kind_Array; + a_type->ast_type = type_node; a_type->Array.elem = type_build_from_ast(alloc, a_node->elem); u32 count = 0; @@ -364,6 +368,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { Type* s_type = bh_alloc(alloc, sizeof(Type)); s_node->stcache = s_type; s_type->kind = Type_Kind_Struct; + s_type->ast_type = type_node; s_type->Struct.unique_id = next_unique_id++; s_type->Struct.name = s_node->name; @@ -476,6 +481,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { enum_node->etcache = enum_type; enum_type->kind = Type_Kind_Enum; + enum_type->ast_type = type_node; enum_type->Enum.unique_id = next_unique_id++; enum_type->Enum.backing = enum_node->backing_type; enum_type->Enum.name = enum_node->name; @@ -484,18 +490,26 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { } case Ast_Kind_Slice_Type: { - return type_make_slice(alloc, type_build_from_ast(alloc, ((AstSliceType *) type_node)->elem)); + Type* slice_type = type_make_slice(alloc, type_build_from_ast(alloc, ((AstSliceType *) type_node)->elem)); + slice_type->ast_type = type_node; + return slice_type; } case Ast_Kind_DynArr_Type: { - return type_make_dynarray(alloc, type_build_from_ast(alloc, ((AstDynArrType *) type_node)->elem)); + Type* dynarr_type = type_make_dynarray(alloc, type_build_from_ast(alloc, ((AstDynArrType *) type_node)->elem)); + dynarr_type->ast_type = type_node; + return dynarr_type; } - case Ast_Kind_VarArg_Type: - return type_make_varargs(alloc, type_build_from_ast(alloc, ((AstVarArgType *) type_node)->elem)); + case Ast_Kind_VarArg_Type: { + Type* va_type = type_make_varargs(alloc, type_build_from_ast(alloc, ((AstVarArgType *) type_node)->elem)); + va_type->ast_type = type_node; + return va_type; + } - case Ast_Kind_Basic_Type: + case Ast_Kind_Basic_Type: { return ((AstBasicType *) type_node)->type; + } case Ast_Kind_Type_Alias: return type_build_from_ast(alloc, ((AstTypeAlias *) type_node)->to); @@ -504,7 +518,6 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return ((AstTypeRawAlias *) type_node)->to; case Ast_Kind_Poly_Struct_Type: - // @Cleanup: Replace this with a proper onyx_report_error. - brendanfh 2020/09/14 onyx_report_error(type_node->token->pos, "This structure is polymorphic, which means you need to provide arguments to it to make it a concrete structure. " "This error message is probably in the wrong place, so look through your code for uses of this struct.");