"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/onyx",
- "args": ["progs/basic.onyx"],
+ "args": ["progs/test.onyx"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
Example use:
{{{
ptr: ^i32 = 0; // Address starting at 0
- ptr_ptr := ^ptr;
+ ptr_ptr := *ptr;
}}}
struct AstType { AstKind kind; u32 flags; char* name; };
struct AstBasicType { AstType base; Type* type; };
struct AstPointerType { AstType base; AstType* elem; };
-struct AstFunctionType { AstType base; bh_arr(AstType *) params; AstType* results; };
+struct AstFunctionType { AstType base; AstType* return_type; u64 param_count; AstType* params[]; };
// Top level nodes
struct AstBinding { AstTyped base; AstNode* node; };
typedef struct Type Type;
#define TYPE_KINDS \
- TYPE_KIND(Basic, TypeBasic) \
- TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) // TypePointer utilizes the elements of TypeBasic
+ TYPE_KIND(Basic, TypeBasic) \
+ TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \
+ TYPE_KIND(Function, struct { Type *return_type; u64 param_count; Type* params[]; })
typedef enum TypeKind {
Type_Kind_Invalid,
struct Type {
TypeKind kind;
+ u32 flags;
+
union {
#define TYPE_KIND(k, ...) Type##k k;
TYPE_KINDS
#undef TYPE_KIND
};
-
- u32 flags;
};
extern Type basic_types[];
-use "progs/test"
-
other_value :: proc (n: i32) -> i32 {
return 8675309 + something_else(n) + global_value;
}
local_brute();
}
-
// This is the entry point
main2 :: proc #export {
i := 0;
return 1;
}
- if (callee->base.kind != Ast_Kind_Function) {
+ if (callee->base.type == NULL) {
+ callee->base.type = type_build_from_ast(state->node_allocator, callee->base.type_node);
+ }
+
+ if (callee->base.type->kind != Type_Kind_Function) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION,
call->base.token->pos,
onyx_token_null_toggle(callee->base.token);
}
- if (callee->base.type == NULL) {
- callee->base.type = type_build_from_ast(state->node_allocator, callee->base.type_node);
- }
- call->base.type = callee->base.type;
+ call->base.type = callee->base.type->Function.return_type;
AstLocal* formal_param = callee->params;
AstArgument* actual_param = call->arguments;
assert(expr->type != NULL);
break;
+ case Ast_Kind_Function: break;
+
default:
retval = 1;
DEBUG_HERE;
}
}
- // NOTE: Acutally the return type
if (func->base.type == NULL) {
func->base.type = type_build_from_ast(state->node_allocator, func->base.type_node);
}
}
}
- state->expected_return_type = func->base.type;
+ state->expected_return_type = func->base.type->Function.return_type;
if (func->body) {
return check_block(state, func->body);
}
AstLocal* params = parse_function_params(parser);
func_def->params = params;
+ AstType* return_type = (AstType *) &basic_type_void;
if (parser->curr_token->type == Token_Type_Right_Arrow) {
expect(parser, Token_Type_Right_Arrow);
- AstType* return_type = parse_type(parser);
- func_def->base.type_node = return_type;
- } else {
- func_def->base.type_node = (AstType *) &basic_type_void;
+ return_type = parse_type(parser);
+ }
+
+ u64 param_count = 0;
+ for (AstLocal* param = params;
+ param != NULL;
+ param = (AstLocal *) param->base.next)
+ param_count++;
+
+ AstFunctionType* type_node = bh_alloc(parser->allocator, sizeof(AstFunctionType) + param_count * sizeof(AstType *));
+ type_node->base.kind = Ast_Kind_Function_Type;
+ type_node->param_count = param_count;
+ type_node->return_type = return_type;
+
+ u32 i = 0;
+ for (AstLocal* param = params;
+ param != NULL;
+ param = (AstLocal *) param->base.next) {
+ type_node->params[i] = param->base.type_node;
+ i++;
}
+ func_def->base.type_node = (AstType *) type_node;
+
func_def->body = parse_block(parser);
return func_def;
return type;
}
+ if (type->kind == Ast_Kind_Function_Type) {
+ AstFunctionType* ftype = (AstFunctionType *) type;
+
+ ftype->return_type = symres_type(state, ftype->return_type);
+
+ if (ftype->param_count > 0)
+ fori (i, 0, ftype->param_count - 1) {
+ ftype->params[i] = symres_type(state, ftype->params[i]);
+ }
+
+ return type;
+ }
+
assert(("Bad type node", 0));
return NULL;
}
static void symres_call(OnyxSemPassState* state, AstCall* call) {
AstNode* callee = symbol_resolve(state, call->callee->token);
- if (callee) call->callee = callee;
- else DEBUG_HERE;
+ if (callee)
+ call->callee = callee;
+ else {
+ onyx_token_null_toggle(call->callee->token);
+ onyx_message_add(state->msgs,
+ ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL,
+ call->callee->token->pos,
+ call->callee->token->text);
+ onyx_token_null_toggle(call->callee->token);
+ return;
+ }
symres_statement_chain(state, (AstNode *) call->arguments, (AstNode **) &call->arguments);
}
// NOTE: This is a good case, since it means the symbol is already resolved
case Ast_Kind_Local: break;
+ case Ast_Kind_Function:
case Ast_Kind_Literal:
(*expr)->type_node = symres_type(state, (*expr)->type_node);
break;
}
if (func->base.type_node != NULL) {
- if (func->base.type_node->kind == Ast_Kind_Symbol) {
- func->base.type_node = symres_type(state, func->base.type_node);
- }
+ func->base.type_node = symres_type(state, func->base.type_node);
}
symres_block(state, func->body);
symbol_basic_type_introduce(state, &basic_type_f64);
symbol_basic_type_introduce(state, &basic_type_rawptr);
- // NOTE: Introduce all global symbols
- // bh_arr_each(AstGlobal *, global, program->globals)
- // if (!symbol_unique_introduce(state, (AstNode *) *global)) return;
-
- // bh_arr_each(AstFunction *, function, program->functions)
- // if (!symbol_unique_introduce(state, (AstNode *) *function)) return;
-
- // bh_arr_each(AstForeign *, foreign, program->foreigns) {
- // AstKind import_kind = (*foreign)->import->kind;
-
- // if (import_kind == Ast_Kind_Function || import_kind == Ast_Kind_Global)
- // if (!symbol_unique_introduce(state, (*foreign)->import)) return;
- // }
-
- // // NOTE: Then, resolve all symbols in all functions
- // bh_arr_each(AstForeign *, foreign, program->foreigns) {
- // if ((*foreign)->import->kind == Ast_Kind_Function) {
- // symres_function(state, (AstFunction *) (*foreign)->import);
- // }
- // }
-
bh_arr_each(AstBinding *, binding, program->top_level_bindings)
if (!symbol_unique_introduce(state, (*binding)->base.token, (*binding)->node)) return;
// NOTE: These have to be in the same order as Basic
Type basic_types[] = {
- { Type_Kind_Basic, { Basic_Kind_Void, 0, 0, "void" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_Void, 0, 0, "void" } },
- { Type_Kind_Basic, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, "bool" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, "bool" } },
- { Type_Kind_Basic, { Basic_Kind_I8, Basic_Flag_Integer, 1, "i8" } },
- { Type_Kind_Basic, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, "u8" } },
- { Type_Kind_Basic, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } },
- { Type_Kind_Basic, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, "u16" } },
- { Type_Kind_Basic, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } },
- { Type_Kind_Basic, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, "u32" } },
- { Type_Kind_Basic, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } },
- { Type_Kind_Basic, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, "u64" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I8, Basic_Flag_Integer, 1, "i8" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, "u8" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, "u16" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, "u32" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, "u64" } },
- { Type_Kind_Basic, { Basic_Kind_F32, Basic_Flag_Float, 4, "f32" } },
- { Type_Kind_Basic, { Basic_Kind_F64, Basic_Flag_Float, 8, "f64" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_F32, Basic_Flag_Float, 4, "f32" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_F64, Basic_Flag_Float, 8, "f64" } },
- { Type_Kind_Basic, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, "rawptr" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, "rawptr" } },
};
b32 types_are_compatible(Type* t1, Type* t2) {
return (Type *) ptr_type;
}
+ case Ast_Kind_Function_Type: {
+ AstFunctionType* ftype_node = (AstFunctionType *) type_node;
+ u64 param_count = ftype_node->param_count;
+
+ Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count);
+
+ func_type->kind = Type_Kind_Function;
+ func_type->Function.param_count = param_count;
+ func_type->Function.return_type = type_build_from_ast(alloc, ftype_node->return_type);
+
+ if (param_count > 0)
+ fori (i, 0, param_count - 1) {
+ func_type->Function.params[i] = type_build_from_ast(alloc, ftype_node->params[i]);
+ }
+
+ return func_type;
+ }
+
case Ast_Kind_Basic_Type:
return ((AstBasicType *) type_node)->type;
static char type_repr_buf[128];
char* t = type_repr_buf;
- AstLocal* param = fd->params;
- i32 param_count = 0;
- while (param) {
+ Type** param_type = fd->base.type->Function.params;
+ i32 param_count = fd->base.type->Function.param_count;
+ i32 params_left = param_count;
+ while (params_left-- > 0) {
// HACK: Using these directly as part of a string feels weird but they are
// valid characters so I don't think it is going to be much of an issue
- *(t++) = (char) onyx_type_to_wasm_type(param->base.type);
- param_count++;
- param = (AstLocal *) param->base.next;
+ *(t++) = (char) onyx_type_to_wasm_type(*param_type);
+ param_type++;
}
*(t++) = ':';
- WasmType return_type = onyx_type_to_wasm_type(fd->base.type);
+ WasmType return_type = onyx_type_to_wasm_type(fd->base.type->Function.return_type);
*(t++) = (char) return_type;
*t = '\0';