From: Brendan Hansen Date: Tue, 15 Dec 2020 23:21:20 +0000 (-0600) Subject: added very basics of array literals; not very useful now X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=2870f256332c895601ff7e47fe0f3c6f65119e7b;p=onyx.git added very basics of array literals; not very useful now --- diff --git a/.vimspector.json b/.vimspector.json index 051f9127..b1d77d0a 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -6,7 +6,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/onyx", - "args": ["-verbose", "tests/hello_world.onyx"], + "args": ["--verbose", "progs/odin_example.onyx"], "stopAtEntry": true, "cwd": "~/dev/c/onyx", "environment": [], diff --git a/docs/todo b/docs/todo index d7abe558..d642885b 100644 --- a/docs/todo +++ b/docs/todo @@ -44,6 +44,13 @@ Language Cohesion: of technical laziness. Cleaning up these areas will help the language feel more cohesive and put together. + [X] Add array literals; The semantics of how array literals will work in + terms of being an value that can be passed around have not been solidified, + but there are many circumstances where having array literals for static + constant data (such as MD5 hash vectors) would be useful. + + Array literals work only for static constant data outside of procedures. + [X] Struct literals can only have 1 level of package before the struct name. This is because packages were not able to be nested, so having arbitrary package levels before a struct literal was not necessary. diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index ae3c5bf6..f46e4e89 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -23,6 +23,7 @@ typedef struct AstSizeOf AstSizeOf; typedef struct AstAlignOf AstAlignOf; typedef struct AstFileContents AstFileContents; typedef struct AstStructLiteral AstStructLiteral; +typedef struct AstArrayLiteral AstArrayLiteral; typedef struct AstReturn AstReturn; typedef struct AstJump AstJump; @@ -138,6 +139,7 @@ typedef enum AstKind { Ast_Kind_Align_Of, Ast_Kind_File_Contents, Ast_Kind_Struct_Literal, + Ast_Kind_Array_Literal, Ast_Kind_If, Ast_Kind_For, @@ -457,6 +459,13 @@ struct AstStructLiteral { bh_arr(AstStructMember *) named_values; bh_arr(AstTyped *) values; }; +struct AstArrayLiteral { + AstTyped_base; + + AstTyped *atnode; + + bh_arr(AstTyped *) values; +}; struct AstCall { AstTyped_base; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index e96279ab..7dbe2a4c 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -135,6 +135,7 @@ Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node); Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func); Type* type_make_pointer(bh_allocator alloc, Type* to); +Type* type_make_array(bh_allocator alloc, Type* to, u32 count); Type* type_make_slice(bh_allocator alloc, Type* of); Type* type_make_dynarray(bh_allocator alloc, Type* of); Type* type_make_varargs(bh_allocator alloc, Type* of); diff --git a/onyx b/onyx index 922dbddb..07ed65dd 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 4df1e728..ba1324b4 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -17,6 +17,7 @@ CHECK(call, AstCall* call); CHECK(binaryop, AstBinaryOp** pbinop, b32 assignment_is_ok); CHECK(unaryop, AstUnaryOp** punop); CHECK(struct_literal, AstStructLiteral* sl); +CHECK(array_literal, AstArrayLiteral* al); CHECK(expression, AstTyped** expr); CHECK(address_of, AstAddressOf* aof); CHECK(dereference, AstDereference* deref); @@ -909,6 +910,39 @@ b32 check_struct_literal(AstStructLiteral* sl) { return 0; } +b32 check_array_literal(AstArrayLiteral* al) { + fill_in_type((AstTyped *) al); + + assert(al->type->kind == Type_Kind_Array); + + if (al->type->Array.count != bh_arr_length(al->values)) { + onyx_report_error(al->token->pos, "Wrong array size (%d) for number of values (%d).", + al->type->Array.count, bh_arr_length(al->values)); + return 1; + } + + b32 all_comptime = 1; + + Type* elem_type = al->type->Array.elem; + bh_arr_each(AstTyped *, expr, al->values) { + if (check_expression(expr)) return 1; + if (((*expr)->flags & Ast_Flag_Comptime) == 0) + all_comptime = 0; + + if (!type_check_or_auto_cast(expr, elem_type)) { + onyx_report_error((*expr)->token->pos, "Mismatched types for value of in array, expected '%s', got '%s'.", + type_get_name(elem_type), + type_get_name((*expr)->type)); + return 1; + } + } + + if (all_comptime) + al->flags |= Ast_Flag_Comptime; + + return 0; +} + b32 check_address_of(AstAddressOf* aof) { if (check_expression(&aof->expr)) return 1; @@ -1188,6 +1222,10 @@ b32 check_expression(AstTyped** pexpr) { retval = check_struct_literal((AstStructLiteral *) expr); break; + case Ast_Kind_Array_Literal: + retval = check_array_literal((AstArrayLiteral *) expr); + break; + case Ast_Kind_Function: // NOTE: Will need something like this at some point // AstFunction* func = (AstFunction *) expr; diff --git a/src/onyxparser.c b/src/onyxparser.c index e347af27..dd76093d 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -25,6 +25,7 @@ static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type); static AstNumLit* parse_int_literal(OnyxParser* parser); static AstNumLit* parse_float_literal(OnyxParser* parser); static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret); +static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret); static AstTyped* parse_factor(OnyxParser* parser); static AstTyped* parse_expression(OnyxParser* parser); static AstIfWhile* parse_if_stmt(OnyxParser* parser); @@ -240,6 +241,34 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, Ast return 1; } +static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) { + if (parser->curr->type != '.' + || (parser->curr + 1)->type != '[') return 0; + + AstArrayLiteral* al = make_node(AstArrayLiteral, Ast_Kind_Array_Literal); + al->token = parser->curr; + al->atnode = left; + + bh_arr_new(global_heap_allocator, al->values, 4); + fori (i, 0, 4) al->values[i] = NULL; + + expect_token(parser, '.'); + expect_token(parser, '['); + while (parser->curr->type != ']') { + AstTyped* value = parse_expression(parser); + bh_arr_push(al->values, value); + + if (parser->curr->type != ']') + expect_token(parser, ','); + } + + expect_token(parser, ']'); + + *ret = (AstTyped *) al; + + return 1; +} + // ( ) // - // ! @@ -534,6 +563,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { case '.': { if (parse_possible_struct_literal(parser, retval, &retval)) return retval; + if (parse_possible_array_literal(parser, retval, &retval)) return retval; consume_token(parser); AstFieldAccess* field = make_node(AstFieldAccess, Ast_Kind_Field_Access); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index d116a9ca..9107fe66 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -350,6 +350,30 @@ static void symres_struct_literal(AstStructLiteral* sl) { bh_arr_each(AstTyped *, expr, sl->values) symres_expression(expr); } +static void symres_array_literal(AstArrayLiteral* al) { + if (al->atnode != NULL) symres_expression(&al->atnode); + if (!node_is_type((AstNode *) al->atnode)) { + onyx_report_error(al->token->pos, "Array type is not a type."); + return; + } + + al->atnode = (AstTyped *) symres_type((AstType *) al->atnode); + if (al->atnode == NULL || al->atnode->kind == Ast_Kind_Error || al->atnode->kind == Ast_Kind_Symbol) return; + + al->type_node = (AstType *) al->atnode; + while (al->type_node->kind == Ast_Kind_Type_Alias) + al->type_node = ((AstTypeAlias *) al->type_node)->to; + + al->type = type_build_from_ast(semstate.allocator, al->type_node); + if (al->type == NULL) return; + + al->type = type_make_array(semstate.allocator, al->type, bh_arr_length(al->values)); + if (al->type == NULL) return; + + bh_arr_each(AstTyped *, expr, al->values) + symres_expression(expr); +} + static void symres_expression(AstTyped** expr) { switch ((*expr)->kind) { case Ast_Kind_Symbol: @@ -404,6 +428,10 @@ static void symres_expression(AstTyped** expr) { symres_struct_literal((AstStructLiteral *)(*expr)); break; + case Ast_Kind_Array_Literal: + symres_array_literal((AstArrayLiteral *)(*expr)); + break; + default: break; } } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index c1ff7363..dfe7a91c 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -507,6 +507,17 @@ Type* type_make_pointer(bh_allocator alloc, Type* to) { return ptr_type; } +Type* type_make_array(bh_allocator alloc, Type* to, u32 count) { + Type* arr_type = bh_alloc_item(alloc, Type); + + arr_type->kind = Type_Kind_Array; + arr_type->Array.count = count; + arr_type->Array.elem = to; + arr_type->Array.size = count * type_size_of(to); + + return arr_type; +} + Type* type_make_slice(bh_allocator alloc, Type* of) { Type* slice_type = bh_alloc(alloc, sizeof(Type)); slice_type->kind = Type_Kind_Slice; diff --git a/src/onyxutils.c b/src/onyxutils.c index e689b99a..fa62fc9f 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -78,6 +78,7 @@ static const char* ast_node_names[] = { "ALIGN OF", "FILE CONTENTS", "STRUCT LITERAL", + "ARRAY LITERAL", "IF", "FOR", diff --git a/src/onyxwasm.c b/src/onyxwasm.c index be107baf..26f14bd5 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -2204,6 +2204,11 @@ EMIT_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_Array_Literal: { + assert(("Array literals are not allowed as expressions currently. This will be added in a future update.", 0)); + break; + } + case Ast_Kind_Function: { i32 elemidx = get_element_idx(mod, (AstFunction *) expr); WID(WI_I32_CONST, elemidx); @@ -2891,6 +2896,20 @@ static void emit_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) { static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) { switch (node->kind) { + case Ast_Kind_Array_Literal: { + AstArrayLiteral* al = (AstArrayLiteral *) node; + + i32 i = 0; + i32 elem_size = type_size_of(al->type->Array.elem); + + bh_arr_each(AstTyped *, expr, al->values) { + emit_raw_data(mod, bh_pointer_add(data, i * elem_size), *expr); + i++; + } + + break; + } + case Ast_Kind_StrLit: { AstStrLit* sl = (AstStrLit *) node;