added very basics of array literals; not very useful now
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 15 Dec 2020 23:21:20 +0000 (17:21 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 15 Dec 2020 23:21:20 +0000 (17:21 -0600)
.vimspector.json
docs/todo
include/onyxastnodes.h
include/onyxtypes.h
onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxutils.c
src/onyxwasm.c

index 051f91275bfb03125b6841803b193bf67fdb74bb..b1d77d0af774d9f3593db933ef098adfe65b339d 100644 (file)
@@ -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": [],
index d7abe558cf939f5fa193ca4341d5eb00870c3969..d642885b9be435ef7c588e9601c106c2e30200ae 100644 (file)
--- 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.
index ae3c5bf642b1a2e95b07d2398ba34cbd17b57464..f46e4e89f02444d519fee6dc69ffb505a17b57a9 100644 (file)
@@ -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;
 
index e96279abf02f85b722559582a4f34d549711f6fe..7dbe2a4cf454e3cda974ca35f9143032e0381a42 100644 (file)
@@ -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 922dbddb8da2712f09c9e105b081ef0ff8352ce0..07ed65ddc6f1a3166f84c6f9a20047835878d6c0 100755 (executable)
Binary files a/onyx and b/onyx differ
index 4df1e7283a09b3fc017dcb6514ebe476a427b9a0..ba1324b4e8c161d19d555e84162979dba1cc112b 100644 (file)
@@ -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;
index e347af2786b4d3544ca402965e2ec369b72ccc26..dd76093de5dd93d80717823bcfe2810a875ea3dd 100644 (file)
@@ -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;
+}
+
 // ( <expr> )
 // - <factor>
 // ! <factor>
@@ -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);
index d116a9caa403b9fca2b285a993ef3a02bf0dfbac..9107fe6628448083307d297b254d4b5b8a7d5a54 100644 (file)
@@ -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;
     }
 }
index c1ff7363c45d586226b072310870320b48480952..dfe7a91cef3a41a03123400472945fed0c2ea4a7 100644 (file)
@@ -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;
index e689b99a71f4dda06358f084737b9087b01f6c52..fa62fc9f71caefbdc8ce32cc24b40bfef189bb7c 100644 (file)
@@ -78,6 +78,7 @@ static const char* ast_node_names[] = {
     "ALIGN OF",
     "FILE CONTENTS",
     "STRUCT LITERAL",
+    "ARRAY LITERAL",
 
     "IF",
     "FOR",
index be107baff3483b0fe90274b0ca5d3ddc42673bc7..26f14bd57e60a73ae3b7b927ac3a606236aa209c 100644 (file)
@@ -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;