"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": [],
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.
typedef struct AstAlignOf AstAlignOf;
typedef struct AstFileContents AstFileContents;
typedef struct AstStructLiteral AstStructLiteral;
+typedef struct AstArrayLiteral AstArrayLiteral;
typedef struct AstReturn AstReturn;
typedef struct AstJump AstJump;
Ast_Kind_Align_Of,
Ast_Kind_File_Contents,
Ast_Kind_Struct_Literal,
+ Ast_Kind_Array_Literal,
Ast_Kind_If,
Ast_Kind_For,
bh_arr(AstStructMember *) named_values;
bh_arr(AstTyped *) values;
};
+struct AstArrayLiteral {
+ AstTyped_base;
+
+ AstTyped *atnode;
+
+ bh_arr(AstTyped *) values;
+};
struct AstCall {
AstTyped_base;
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);
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);
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;
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;
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);
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>
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);
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:
symres_struct_literal((AstStructLiteral *)(*expr));
break;
+ case Ast_Kind_Array_Literal:
+ symres_array_literal((AstArrayLiteral *)(*expr));
+ break;
+
default: break;
}
}
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;
"ALIGN OF",
"FILE CONTENTS",
"STRUCT LITERAL",
+ "ARRAY LITERAL",
"IF",
"FOR",
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);
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;