[ ] Array literals
+ [ ] Struct literals
+
+ [ ] Top level variable initialization
+ - Works for numeric literals
+
+ [ ] 'use' enums and packages at an arbitrary scope
+
[ ] Better checking for casts
- Checking which things are allowed to cast to/from should be checked in the checker,
not in the wasm generatation
// Top level nodes
struct AstBinding { AstTyped_base; AstNode* node; };
-struct AstMemRes { AstTyped_base; u64 addr; }; // HACK: This has to be the same size as AstDereference
+struct AstMemRes { AstTyped_base; u64 addr; AstTyped *initial_value; }; // HACK: This has to be the same size or bigger as AstDereference
struct AstIncludeFile { AstNode_base; OnyxToken *filename; };
struct AstUsePackage {
AstNode_base;
b32 type_is_bool(Type* type);
b32 type_is_integer(Type* type);
b32 type_is_numeric(Type* type);
+b32 type_is_compound(Type* type);
b32 type_results_in_void(Type* type);
#endif // #ifndef ONYX_TYPES
z = v.z + u.z;
}
+some_value := #char "A";
+
start :: proc #export {
heap_init();
print("Hello, World!");
+ print_hex(cast(u64) some_value);
print("Hello, World!");
print_ptr(__heap_start);
print_ptr(__stack_base);
print_bin(42l);
print_hex(42l);
- for i: #char "a", #char "f" {
- print_hex(cast(u64) i);
- }
+ for i: #char "a", #char "f" do print_hex(cast(u64) i);
a := 12345;
CHECK(overloaded_function, AstOverloadedFunction* func);
CHECK(struct, AstStructType* s_node);
CHECK(function_header, AstFunction* func);
+CHECK(memres, AstMemRes* memres);
static inline void fill_in_type(AstTyped* node) {
if (node->type == NULL)
return 0;
}
+CHECK(memres, AstMemRes* memres) {
+ fill_in_type((AstTyped *) memres);
+
+ if (memres->initial_value != NULL) {
+ fill_in_type(memres->initial_value);
+
+ Type* memres_type = memres->type;
+ if (!type_is_compound(memres_type)) memres_type = memres_type->Pointer.elem;
+
+ if (!types_are_compatible(memres_type, memres->initial_value->type)) {
+ onyx_message_add(Msg_Type_Binop_Mismatch,
+ memres->token->pos,
+ type_get_name(memres_type),
+ type_get_name(memres->initial_value->type));
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
CHECK(node, AstNode* node) {
switch (node->kind) {
case Ast_Kind_Function: return check_function((AstFunction *) node);
if (check_struct((AstStructType *) entity->type_alias)) return;
break;
+ case Entity_Type_Memory_Reservation:
+ if (check_memres(entity->mem_res)) return;
+ break;
+
case Entity_Type_Enum: break;
case Entity_Type_String_Literal: break;
case Entity_Type_Use_Package: break;
- case Entity_Type_Memory_Reservation: break;
-
default: DEBUG_HERE; break;
}
}
negate_node->operation = Unary_Op_Negate;
negate_node->expr = factor;
- if ((factor->flags & Ast_Flag_Comptime) != 0) {
- negate_node->flags |= Ast_Flag_Comptime;
- }
-
retval = (AstTyped *) negate_node;
break;
}
not_node->token = expect_token(parser, '!');
not_node->expr = parse_factor(parser);
- if ((not_node->expr->flags & Ast_Flag_Comptime) != 0) {
- not_node->flags |= Ast_Flag_Comptime;
- }
-
retval = (AstTyped *) not_node;
break;
}
right = parse_factor(parser);
bin_op->right = right;
-
- if ((left->flags & Ast_Flag_Comptime) != 0 && (right->flags & Ast_Flag_Comptime) != 0) {
- bin_op->flags |= Ast_Flag_Comptime;
- }
}
}
return (AstNode *) binding;
} else {
- if (parser->curr->type == '=') {
- onyx_message_add(Msg_Type_Literal,
- parser->curr->pos,
- "assigning initial values to memory reservations isn't allowed yet.");
- break;
- }
-
AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres);
memres->token = symbol;
- memres->type_node = parse_type(parser);
+
+ if (parser->curr->type == '=') {
+ consume_token(parser);
+ memres->initial_value = parse_expression(parser);
+
+ } else {
+ memres->type_node = parse_type(parser);
+
+ if (parser->curr->type == '=') {
+ consume_token(parser);
+ memres->initial_value = parse_expression(parser);
+ }
+ }
if (is_private)
memres->flags |= Ast_Flag_Private_Package;
static void symres_memres(AstMemRes** memres) {
(*memres)->type_node = symres_type((*memres)->type_node);
- if ((*memres)->type_node == NULL) return;
+ if ((*memres)->initial_value != NULL) {
+ symres_expression(&(*memres)->initial_value);
+
+ if (((*memres)->initial_value->flags & Ast_Flag_Comptime) == 0) {
+ onyx_message_add(Msg_Type_Literal,
+ (*memres)->initial_value->token->pos,
+ "top level expressions must be compile time known");
+ return;
+ }
+
+ if ((*memres)->type_node == NULL)
+ (*memres)->type_node = (*memres)->initial_value->type_node;
+
+ } else {
+ if ((*memres)->type_node == NULL) return;
+ }
(*memres)->type = type_build_from_ast(semstate.allocator, (*memres)->type_node);
- if ((*memres)->type->kind != Type_Kind_Array && (*memres)->type->kind != Type_Kind_Struct) {
+ if (!type_is_compound((*memres)->type)) {
Type* ptr_type = type_make_pointer(semstate.allocator, (*memres)->type);
(*memres)->type = ptr_type;
return type->Basic.kind >= Basic_Kind_I8 && type->Basic.kind <= Basic_Kind_F64;
}
+b32 type_is_compound(Type* type) {
+ return type->kind == Type_Kind_Array
+ || type->kind == Type_Kind_Struct;
+}
+
b32 type_results_in_void(Type* type) {
return (type == NULL)
|| (type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Void)
bh_arr_push(mod->data, datum);
}
+static void compile_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
+ switch (node->kind) {
+ case Ast_Kind_NumLit: {
+ switch (node->type->Basic.kind) {
+ case Basic_Kind_Bool:
+ case Basic_Kind_I8:
+ case Basic_Kind_U8:
+ case Basic_Kind_I16:
+ case Basic_Kind_U16:
+ case Basic_Kind_I32:
+ case Basic_Kind_U32:
+ case Basic_Kind_Rawptr:
+ *((i32 *) data) = ((AstNumLit *) node)->value.i;
+ return;
+
+ case Basic_Kind_I64:
+ case Basic_Kind_U64:
+ *((i64 *) data) = ((AstNumLit *) node)->value.l;
+ return;
+
+ case Basic_Kind_F32:
+ *((f32 *) data) = ((AstNumLit *) node)->value.f;
+ return;
+
+ case Basic_Kind_F64:
+ *((f64 *) data) = ((AstNumLit *) node)->value.d;
+ return;
+
+ default: break;
+ }
+
+ //fallthrough
+ }
+ default: onyx_message_add(Msg_Type_Literal,
+ node->token->pos,
+ "invalid data");
+ }
+}
+
static void compile_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
- u64 alignment = type_alignment_of(memres->type);
- u64 size = type_size_of(memres->type);
+ Type* effective_type = memres->type;
+ if (!type_is_compound(effective_type)) effective_type = effective_type->Pointer.elem;
+
+ u64 alignment = type_alignment_of(effective_type);
+ u64 size = type_size_of(effective_type);
u32 offset = mod->next_datum_offset;
if (offset % alignment != 0) {
offset += alignment - (offset % alignment);
}
- // WasmDatum datum = {
- // .offset = offset,
- // .length = size,
- // .data = NULL
- // };
+ if (memres->initial_value != NULL) {
+ u8* data = bh_alloc(mod->allocator, size);
+ compile_raw_data(mod, data, memres->initial_value);
+
+ WasmDatum datum = {
+ .offset = offset,
+ .length = size,
+ .data = data,
+ };
+
+ bh_arr_push(mod->data, datum);
+ }
memres->addr = offset;
mod->next_datum_offset = offset + size;
-
- // bh_arr_push(mod->data, datum);
}
static void compile_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {