easier to talk about types in a concrete way (for polymorphism and such),
and would prepare the compiler to output type information into data section.
+ [ ] Switches should have range based statements, i.e.
+ switch expr {
+ case 10 .. 14 do ...
+ }
+
+ The only reason I have not implemented this feature is because it would
+ introduce a slight inconsistency in the language design. Generally, the
+ range (..) operator talks about ranges as inclusive low and exclusive
+ high, which makes sense for for-loops and the like. However, for the switch
+ statement, I think that would be very confusing. In the example above,
+ I would expect the case to trip when `expr` is 14. This isn't a techinal
+ problem; implementing this feature will be fairly straight forward. It
+ is just a language design problems, because it requires a bit of extra
+ thought to remember that ranges in for-loops and slices are NOT inclusive
+ on the upper end.
+
API Expansion:
There are many different places where the standard API for WASI and JS
backends could be improved. Here are some of the target areas.
Type* params[]; \
}) \
TYPE_KIND(Struct, struct { \
+ u64 unique_id; \
char* name; \
u32 size; \
u16 alignment, mem_count; \
TYPE_KIND(Slice, struct { Type *ptr_to_data; }) \
TYPE_KIND(DynArray, struct { Type *ptr_to_data; }) \
TYPE_KIND(VarArgs, struct { Type *ptr_to_data; }) \
- TYPE_KIND(Enum, struct { char* name; Type* backing; })
+ TYPE_KIND(Enum, struct { \
+ u64 unique_id; \
+ char* name; \
+ Type* backing; \
+ })
typedef enum TypeKind {
Type_Kind_Invalid,
Type* type_make_dynarray(bh_allocator alloc, Type* of);
Type* type_make_varargs(bh_allocator alloc, Type* of);
+const char* type_get_unique_name(Type* type);
const char* type_get_name(Type* type);
u32 type_get_alignment_log2(Type* type);
{
"target": "exec",
- "shell_cmd": "/usr/bin/onyx -o \"${folder}/${file_base_name}.wasm\" \"$file\"",
+ "shell_cmd": "/usr/bin/onyx -V -o \"${folder}/${file_base_name}.wasm\" \"$file\"",
"working_dir": "${folder}",
"selector": "source.onyx",
"file_regex": "^\\(([^:]+):([0-9]+),([0-9]+)\\) (.*)",
#include "onyxutils.h"
#include "onyxerrors.h"
+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" } },
s_node->stcache = s_type;
s_type->kind = Type_Kind_Struct;
+ s_type->Struct.unique_id = next_unique_id++;
s_type->Struct.name = s_node->name;
s_type->Struct.mem_count = bh_arr_length(s_node->members);
s_type->Struct.memarr = NULL;
enum_node->etcache = enum_type;
enum_type->kind = Type_Kind_Enum;
+ enum_type->Enum.unique_id = next_unique_id++;
enum_type->Enum.backing = enum_node->backing_type;
enum_type->Enum.name = enum_node->name;
return va_type;
}
+const char* type_get_unique_name(Type* type) {
+ if (type == NULL) return "unknown";
+
+ switch (type->kind) {
+ case Type_Kind_Basic: return type->Basic.name;
+ case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "^%s", type_get_unique_name(type->Pointer.elem));
+ case Type_Kind_Array: return bh_aprintf(global_scratch_allocator, "[%d] %s", type->Array.count, type_get_unique_name(type->Array.elem));
+ case Type_Kind_Struct:
+ if (type->Struct.name)
+ return bh_aprintf(global_scratch_allocator, "%s@%l", type->Struct.name, type->Struct.unique_id);
+ else
+ return bh_aprintf(global_scratch_allocator, "%s@%l", "<anonymous struct>", type->Struct.unique_id);
+ case Type_Kind_Enum:
+ if (type->Enum.name)
+ return bh_aprintf(global_scratch_allocator, "%s@%l", type->Enum.name, type->Enum.unique_id);
+ else
+ return bh_aprintf(global_scratch_allocator, "%s@%l", "<anonymous enum>", type->Enum.unique_id);
+
+ case Type_Kind_Slice: return bh_aprintf(global_scratch_allocator, "[] %s", type_get_unique_name(type->Slice.ptr_to_data->Pointer.elem));
+ case Type_Kind_VarArgs: return bh_aprintf(global_scratch_allocator, "..%s", type_get_unique_name(type->VarArgs.ptr_to_data->Pointer.elem));
+ case Type_Kind_DynArray: return bh_aprintf(global_scratch_allocator, "[..] %s", type_get_unique_name(type->DynArray.ptr_to_data->Pointer.elem));
+
+ case Type_Kind_Function: {
+ char buf[512];
+ fori (i, 0, 512) buf[i] = 0;
+
+ strncat(buf, "proc (", 511);
+ fori (i, 0, type->Function.param_count) {
+ strncat(buf, type_get_unique_name(type->Function.params[i]), 511);
+ if (i != type->Function.param_count - 1)
+ strncat(buf, ", ", 511);
+ }
+
+ strncat(buf, ") -> ", 511);
+ strncat(buf, type_get_unique_name(type->Function.return_type), 511);
+
+ return bh_aprintf(global_scratch_allocator, "%s", buf);
+ }
+
+ default: return "unknown";
+ }
+}
+
const char* type_get_name(Type* type) {
if (type == NULL) return "unknown";
bh_table_each_start(AstNode *, pp->poly_scope->symbols);
strncat(key_buf, key, 1023);
strncat(key_buf, "=", 1023);
- strncat(key_buf, type_get_name(((AstTypeRawAlias *) value)->to), 1023);
+ strncat(key_buf, type_get_unique_name(((AstTypeRawAlias *) value)->to), 1023);
strncat(key_buf, ";", 1023);
bh_table_each_end;
bh_table_each_start(AstNode *, ps_type->scope->symbols);
strncat(key_buf, key, 1023);
strncat(key_buf, "=", 1023);
- strncat(key_buf, type_get_name(((AstTypeRawAlias *) value)->to), 1023);
+ strncat(key_buf, type_get_unique_name(((AstTypeRawAlias *) value)->to), 1023);
strncat(key_buf, ";", 1023);
bh_table_each_end;