#include_file "memory"
#include_file "intrinsics"
-use package builtin { __heap_start }
+use package builtin
use package intrinsics { memory_size, memory_grow }
-// Need to define this somewhere
-null :: cast(rawptr) 0;
-
-AllocAction :: enum {
- Alloc;
- Free;
- Resize;
-}
-
-alloc_proc :: #type proc (rawptr, AllocAction, u32, u32, rawptr) -> rawptr;
-
-Allocator :: struct {
- data: rawptr;
- func: alloc_proc;
-}
-
-alloc :: proc (use a: Allocator, size: u32) -> rawptr {
- return func(data, AllocAction.Alloc, size, 16, null);
-}
-
-resize :: proc (use a: Allocator, ptr: rawptr, size: u32) -> rawptr {
- return func(data, AllocAction.Resize, size, 16, ptr);
-}
-
-free :: proc (use a: Allocator, ptr: rawptr) {
- func(data, AllocAction.Free, 0, 0, ptr);
-}
-
-
-
-
-
-
-
heap_allocator : Allocator;
#private
string :: #type []u8;
cstring :: #type ^u8;
+
+Buffer :: #type []void;
+
+null :: cast(rawptr) 0;
+
+AllocAction :: enum {
+ Alloc;
+ Free;
+ Resize;
+}
+
+allocator_proc :: #type proc (rawptr, AllocAction, u32, u32, rawptr) -> rawptr;
+
+Allocator :: struct {
+ data: rawptr;
+ func: allocator_proc;
+}
+
+alloc :: proc (use a: Allocator, size: u32) -> rawptr {
+ return func(data, AllocAction.Alloc, size, 16, null);
+}
+
+resize :: proc (use a: Allocator, ptr: rawptr, size: u32) -> rawptr {
+ return func(data, AllocAction.Resize, size, 16, ptr);
+}
+
+free :: proc (use a: Allocator, ptr: rawptr) {
+ func(data, AllocAction.Free, 0, 0, ptr);
+}
+
+context : struct {
+ allocator : Allocator;
+ temp_allocator : Allocator;
+}
\ No newline at end of file
package core
-use package builtin { string, cstring }
+use package builtin
use package memory
use package wasi
-Buffer :: #type []void;
-
string_make :: proc #overloaded { string_make_from_cstring }
#private
return string.{ data = c + 1, count = len };
}
-string_builder_add_u64 :: proc (use sb: ^StringBuilder, n: u64) -> ^StringBuilder {
- return string_builder_add_u64_with_base(sb, n, 10l);
-}
-
-string_builder_add_u64_with_base :: proc (use sb: ^StringBuilder, n: u64, base: u64) -> ^StringBuilder {
+string_builder_add_u64 :: proc (use sb: ^StringBuilder, n: u64, base := 10l) -> ^StringBuilder {
buf : [256] u8;
s := u64_to_string(n, base, Buffer.{ cast(rawptr) buf, 256 });
return string_builder_add_string(sb, s);
string_builder_append :: proc #overloaded {
string_builder_add_string,
string_builder_add_cstring,
- string_builder_add_u64_with_base,
string_builder_add_u64,
}
[X] initializers on switch statements
+ [X] default parameters
+ - Must be the last parameters
+
[ ] #file and #line directives
- string and u32 respectively that represent the current file and line number where the directive is
typedef struct AstUsePackage AstUsePackage;
typedef struct AstAlias AstAlias;
typedef struct AstGlobal AstGlobal;
+typedef struct AstParam AstParam;
typedef struct AstFunction AstFunction;
typedef struct AstOverloadedFunction AstOverloadedFunction;
};
};
};
+struct AstParam { AstLocal *local; AstTyped *default_value; };
struct AstFunction {
AstTyped_base;
Scope *scope;
+
+ bh_arr(AstParam) params;
+ AstType* return_type;
+
AstBlock *body;
- AstLocal *params;
bh_arr(AstLocal *) locals;
union {
// NOTE: Inferring and checking types in the tree
void onyx_type_check();
+b32 check_expression(AstTyped** expr);
+
// NOTE: Full semantic pass
void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc);
void onyx_sempass(ProgramInfo* program);
TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \
TYPE_KIND(Function, struct { \
Type *return_type; \
- u64 param_count; \
+ u32 param_count; \
+ u32 needed_param_count; \
Type* params[]; \
}) \
TYPE_KIND(Struct, struct { \
u32 type_alignment_of(Type* type);
Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node);
-Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func, struct AstType* return_type);
+Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func);
Type* type_make_pointer(bh_allocator alloc, Type* to);
Type* type_make_slice(bh_allocator alloc, Type* of);
scope: constant.type.onyx
- match: '\b(true|false|null)\b'
- scope: constant.boolean.onyx
+ scope: constant.numeric.onyx
# Numbers
- match: '\b(-)?[0-9.]+(f|l)?\b'
use package wasi
use package intrinsics
-print_u64_with_base :: proc (n_: u64, base: u64) {
+print_u64_with_base :: proc (n_: u64, base := 10l) {
n := n_;
str: [256] u8;
for i: 0, 256 do str[i] = #char "\0";
return (curr_time - start_time) / 1000000l;
}
-is_prime :: proc (n: u32) -> bool {
+is_prime :: proc (n := 0) -> bool {
sqrt :: cast(i32) (sqrt_f32(cast(f32) n));
for i: 2, sqrt + 1 do if n % i == 0 do return false;
return true;
print("Unexpected token: ");
print_u64_with_base(cast(u64) tokens.data[i].data[0], 16l);
print("\n");
+
+ // This breaks out of the for loop
+ break break;
}
}
}
ss := string_substr("Hello, World!", "World");
if ss.count > 0 do print(ss);
print("\n");
+
+ foobar(10, 1230);
}
+foobar :: proc (a: i32, b := 1, c := 5l) {
+ print_u64_with_base(cast(u64) a);
+ print("\n");
+ print_u64_with_base(cast(u64) b, 16l);
+ print("\n");
+ print_u64_with_base(c);
+ print("\n");
+}
\ No newline at end of file
#include "onyxparser.h"
#include "onyxutils.h"
-#define CHECK(kind, ...) static b32 check_ ## kind (__VA_ARGS__)
+#define CHECK(kind, ...) b32 check_ ## kind (__VA_ARGS__)
CHECK(block, AstBlock* block);
CHECK(statement_chain, AstNode* start);
node->type = type_build_from_ast(semstate.allocator, node->type_node);
}
-CHECK(return, AstReturn* retnode) {
+b32 check_return(AstReturn* retnode) {
if (retnode->expr) {
if (check_expression(&retnode->expr)) return 1;
return 0;
}
-CHECK(if, AstIfWhile* ifnode) {
+b32 check_if(AstIfWhile* ifnode) {
if (ifnode->assignment != NULL) check_statement((AstNode *) ifnode->assignment);
if (check_expression(&ifnode->cond)) return 1;
return 0;
}
-CHECK(while, AstIfWhile* whilenode) {
+b32 check_while(AstIfWhile* whilenode) {
if (whilenode->assignment != NULL) check_statement((AstNode *) whilenode->assignment);
if (check_expression(&whilenode->cond)) return 1;
return 0;
}
-CHECK(for, AstFor* fornode) {
+b32 check_for(AstFor* fornode) {
if (check_expression(&fornode->start)) return 1;
if (check_expression(&fornode->end)) return 1;
if (check_expression(&fornode->step)) return 1;
return 0;
}
-CHECK(switch, AstSwitch* switchnode) {
+b32 check_switch(AstSwitch* switchnode) {
if (switchnode->assignment != NULL) check_statement((AstNode *) switchnode->assignment);
if (check_expression(&switchnode->expr)) return 1;
TypeFunction* ol_type = &overload->type->Function;
- if (ol_type->param_count != call->arg_count) continue;
+ if (call->arg_count < ol_type->needed_param_count) continue;
AstArgument* arg = call->arguments;
Type** param_type = ol_type->params;
return NULL;
}
-CHECK(call, AstCall* call) {
+b32 check_call(AstCall* call) {
AstFunction* callee = (AstFunction *) call->callee;
if (callee->kind == Ast_Kind_Symbol) {
return 1;
}
+ if (callee->kind == Ast_Kind_Function) {
+ if (call->arg_count < bh_arr_length(callee->params)) {
+ AstArgument** last_arg = &call->arguments;
+ while (*last_arg && (*last_arg)->next != NULL)
+ last_arg = (AstArgument **) &(*last_arg)->next;
+
+ while (call->arg_count < bh_arr_length(callee->params)
+ && callee->params[call->arg_count].default_value != NULL) {
+ AstTyped* dv = callee->params[call->arg_count].default_value;
+
+ AstArgument* new_arg = onyx_ast_node_new(semstate.node_allocator, sizeof(AstArgument), Ast_Kind_Argument);
+ new_arg->token = dv->token;
+ new_arg->value = dv;
+ new_arg->type = dv->type;
+ new_arg->next = NULL;
+
+ (*last_arg)->next = (AstNode *) new_arg;
+ last_arg = (AstArgument **) &(*last_arg)->next;
+
+ call->arg_count++;
+ }
+ }
+ }
+
// NOTE: If we calling an intrinsic function, translate the
// call into an intrinsic call node.
if (callee->flags & Ast_Flag_Intrinsic) {
call->type = callee->type->Function.return_type;
- Type** formal_param = &callee->type->Function.params[0];
+ Type **formal_params = callee->type->Function.params;
actual_param = call->arguments;
i32 arg_pos = 0;
- while (formal_param != NULL && actual_param != NULL) {
- if (!types_are_compatible(*formal_param, actual_param->type)) {
+ while (arg_pos < callee->type->Function.param_count && actual_param != NULL) {
+ if (!types_are_compatible(formal_params[arg_pos], actual_param->type)) {
onyx_message_add(Msg_Type_Function_Param_Mismatch,
actual_param->token->pos,
callee->token->text, callee->token->length,
- type_get_name(*formal_param),
+ type_get_name(formal_params[arg_pos]),
arg_pos,
type_get_name(actual_param->type));
return 1;
}
arg_pos++;
- formal_param++;
actual_param = (AstArgument *) actual_param->next;
}
return 1;
}
- if (arg_pos > callee->type->Function.param_count) {
+ if (actual_param != NULL) {
onyx_message_add(Msg_Type_Literal,
call->token->pos,
"too many arguments to function call");
return 0;
}
-CHECK(binop_assignment, AstBinaryOp* binop, b32 assignment_is_ok) {
+b32 check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) {
if (!assignment_is_ok) {
onyx_message_add(Msg_Type_Literal,
binop->token->pos,
return 0;
}
-CHECK(binaryop_compare, AstBinaryOp** pbinop) {
+b32 check_binaryop_compare(AstBinaryOp** pbinop) {
AstBinaryOp* binop = *pbinop;
if (binop->left->type == NULL) {
return 0;
}
-CHECK(binaryop_bool, AstBinaryOp** pbinop) {
+b32 check_binaryop_bool(AstBinaryOp** pbinop) {
AstBinaryOp* binop = *pbinop;
if (binop->left->type == NULL) {
return 0;
}
-CHECK(binaryop, AstBinaryOp** pbinop, b32 assignment_is_ok) {
+b32 check_binaryop(AstBinaryOp** pbinop, b32 assignment_is_ok) {
AstBinaryOp* binop = *pbinop;
if (check_expression(&binop->left)) return 1;
return 0;
}
-CHECK(unaryop, AstUnaryOp** punop) {
+b32 check_unaryop(AstUnaryOp** punop) {
AstUnaryOp* unaryop = *punop;
if (check_expression(&unaryop->expr)) return 1;
return 0;
}
-CHECK(struct_literal, AstStructLiteral* sl) {
+b32 check_struct_literal(AstStructLiteral* sl) {
fill_in_type((AstTyped *) sl);
TypeStruct* st = &sl->type->Struct;
return 0;
}
-CHECK(address_of, AstAddressOf* aof) {
+b32 check_address_of(AstAddressOf* aof) {
if (check_expression(&aof->expr)) return 1;
if (aof->expr->kind != Ast_Kind_Array_Access
return 0;
}
-CHECK(dereference, AstDereference* deref) {
+b32 check_dereference(AstDereference* deref) {
if (check_expression(&deref->expr)) return 1;
if (!type_is_pointer(deref->expr->type)) {
return 0;
}
-CHECK(array_access, AstArrayAccess* aa) {
+b32 check_array_access(AstArrayAccess* aa) {
if (check_expression(&aa->addr)) return 1;
if (check_expression(&aa->expr)) return 1;
return 0;
}
-CHECK(slice, AstSlice* sl) {
+b32 check_slice(AstSlice* sl) {
if (check_expression(&sl->addr)) return 1;
if (check_expression(&sl->lo)) return 1;
if (check_expression(&sl->hi)) return 1;
return 0;
}
-CHECK(field_access, AstFieldAccess** pfield) {
+b32 check_field_access(AstFieldAccess** pfield) {
AstFieldAccess* field = *pfield;
if (check_expression(&field->expr)) return 1;
return 0;
}
-CHECK(size_of, AstSizeOf* so) {
+b32 check_size_of(AstSizeOf* so) {
so->size = type_size_of(type_build_from_ast(semstate.allocator, so->so_type));
return 0;
}
-CHECK(align_of, AstAlignOf* ao) {
+b32 check_align_of(AstAlignOf* ao) {
ao->alignment = type_alignment_of(type_build_from_ast(semstate.allocator, ao->ao_type));
return 0;
}
-CHECK(expression, AstTyped** pexpr) {
+b32 check_expression(AstTyped** pexpr) {
AstTyped* expr = *pexpr;
if (expr->kind > Ast_Kind_Type_Start && expr->kind < Ast_Kind_Type_End) {
onyx_message_add(Msg_Type_Literal,
break;
case Ast_Kind_Function:
+ // NOTE: Will need something like this at some point
+ // AstFunction* func = (AstFunction *) expr;
+ // bh_arr_each(AstParam, param, func->params) {
+ // if (param->default_value != NULL) {
+ // onyx_message_add(Msg_Type_Literal,
+ // func->token->pos,
+ // "cannot use functions with default parameters in this way");
+ // retval = 1;
+ // break;
+ // }
+ // }
+
expr->flags |= Ast_Flag_Function_Used;
break;
return retval;
}
-CHECK(global, AstGlobal* global) {
+b32 check_global(AstGlobal* global) {
fill_in_type((AstTyped *) global);
if (global->type == NULL) {
return 0;
}
-CHECK(statement, AstNode* stmt) {
+b32 check_statement(AstNode* stmt) {
switch (stmt->kind) {
case Ast_Kind_Jump: return 0;
}
}
-CHECK(statement_chain, AstNode* start) {
+b32 check_statement_chain(AstNode* start) {
while (start) {
if (check_statement(start)) return 1;
start = start->next;
return 0;
}
-CHECK(block, AstBlock* block) {
+b32 check_block(AstBlock* block) {
if (check_statement_chain(block->body)) return 1;
bh_table_each_start(AstTyped *, block->scope->symbols);
return 0;
}
-CHECK(function, AstFunction* func) {
+b32 check_function(AstFunction* func) {
semstate.expected_return_type = func->type->Function.return_type;
if (func->body) {
return check_block(func->body);
return 0;
}
-CHECK(overloaded_function, AstOverloadedFunction* func) {
+b32 check_overloaded_function(AstOverloadedFunction* func) {
bh_arr_each(AstTyped *, node, func->overloads) {
if ((*node)->kind == Ast_Kind_Overloaded_Function) {
onyx_message_add(Msg_Type_Literal,
return 0;
}
-CHECK(struct, AstStructType* s_node) {
+b32 check_struct(AstStructType* s_node) {
bh_table(i32) mem_set;
bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members));
return 0;
}
-CHECK(function_header, AstFunction* func) {
- AstLocal *param = func->params;
- while (param != NULL) {
- fill_in_type((AstTyped *) param);
+b32 check_function_header(AstFunction* func) {
+ b32 expect_default_param = 0;
- if (param->type == NULL) {
+ bh_arr_each(AstParam, param, func->params) {
+ AstLocal* local = param->local;
+
+ if (expect_default_param && param->default_value == NULL) {
+ onyx_message_add(Msg_Type_Literal,
+ local->token->pos,
+ "all parameters must have default values after the first default valued parameter.");
+ return 1;
+ }
+
+ if (param->default_value != NULL) expect_default_param = 1;
+
+ fill_in_type((AstTyped *) local);
+
+ if (local->type == NULL) {
onyx_message_add(Msg_Type_Literal,
- param->token->pos,
+ local->token->pos,
"function parameter types must be known");
return 1;
}
- if (param->type->kind != Type_Kind_Array
- && type_size_of(param->type) == 0) {
+ if (local->type->kind != Type_Kind_Array
+ && type_size_of(local->type) == 0) {
onyx_message_add(Msg_Type_Literal,
- param->token->pos,
+ local->token->pos,
"function parameters must have non-void types");
return 1;
}
-
- param = (AstLocal *) param->next;
}
- fill_in_type((AstTyped *) func);
+ func->type = type_build_function_type(semstate.node_allocator, func);
if ((func->flags & Ast_Flag_Exported) != 0) {
if ((func->flags & Ast_Flag_Foreign) != 0) {
return 0;
}
-CHECK(memres, AstMemRes* memres) {
+b32 check_memres(AstMemRes* memres) {
fill_in_type((AstTyped *) memres);
if (memres->initial_value != NULL) {
return 0;
}
-CHECK(node, AstNode* node) {
+b32 check_node(AstNode* node) {
switch (node->kind) {
case Ast_Kind_Function: return check_function((AstFunction *) node);
case Ast_Kind_Overloaded_Function: return check_overloaded_function((AstOverloadedFunction *) node);
static AstNode* parse_statement(OnyxParser* parser);
static AstType* parse_type(OnyxParser* parser);
static AstStructType* parse_struct(OnyxParser* parser);
-static AstLocal* parse_function_params(OnyxParser* parser);
+static void parse_function_params(OnyxParser* parser, AstFunction* func);
static b32 parse_possible_directive(OnyxParser* parser, const char* dir);
static AstFunction* parse_function_definition(OnyxParser* parser);
static AstTyped* parse_global_declaration(OnyxParser* parser);
// e
// '(' (<symbol>: <type>,?)* ')'
-static AstLocal* parse_function_params(OnyxParser* parser) {
+static void parse_function_params(OnyxParser* parser, AstFunction* func) {
if (parser->curr->type != '(')
- return NULL;
+ return;
expect_token(parser, '(');
if (parser->curr->type == ')') {
consume_token(parser);
- return NULL;
+ return;
}
- AstLocal* first_param = NULL;
- AstLocal* curr_param = NULL;
- AstLocal* trailer = NULL;
+ AstParam curr_param = { 0 };
b32 param_use = 0;
OnyxToken* symbol;
while (parser->curr->type != ')') {
- if (parser->hit_unexpected_token) return first_param;
+ if (parser->hit_unexpected_token) return;
if (parser->curr->type == Token_Type_Keyword_Use) {
consume_token(parser);
symbol = expect_token(parser, Token_Type_Symbol);
expect_token(parser, ':');
- curr_param = make_node(AstLocal, Ast_Kind_Param);
- curr_param->token = symbol;
- curr_param->flags |= Ast_Flag_Const;
- curr_param->type_node = parse_type(parser);
+ curr_param.local = make_node(AstLocal, Ast_Kind_Param);
+ curr_param.local->token = symbol;
+ curr_param.local->flags |= Ast_Flag_Const;
if (param_use) {
- curr_param->flags |= Ast_Flag_Param_Use;
+ curr_param.local->flags |= Ast_Flag_Param_Use;
param_use = 0;
}
- if (first_param == NULL) first_param = curr_param;
+ if (parser->curr->type != '=') {
+ curr_param.local->type_node = parse_type(parser);
+ }
+
+ if (parser->curr->type == '=') {
+ consume_token(parser);
+
+ curr_param.default_value = parse_expression(parser);
+ }
- curr_param->next = NULL;
- if (trailer) trailer->next = (AstNode *) curr_param;
+ bh_arr_push(func->params, curr_param);
- trailer = curr_param;
+ curr_param.default_value = NULL;
if (parser->curr->type != ')')
expect_token(parser, ',');
}
consume_token(parser); // Skip the )
- return first_param;
+ return;
}
// e
// 'proc' <directive>* <func_params> ('->' <type>)? <block>
static AstFunction* parse_function_definition(OnyxParser* parser) {
AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
- bh_arr_new(global_heap_allocator, func_def->locals, 4);
func_def->token = expect_token(parser, Token_Type_Keyword_Proc);
+ bh_arr_new(global_heap_allocator, func_def->locals, 4);
+ bh_arr_new(global_heap_allocator, func_def->params, 4);
+
while (parser->curr->type == '#') {
if (parse_possible_directive(parser, "overloaded")) {
AstOverloadedFunction* ofunc = make_node(AstOverloadedFunction, Ast_Kind_Overloaded_Function);
}
}
- AstLocal* params = parse_function_params(parser);
- func_def->params = params;
+ parse_function_params(parser, func_def);
AstType* return_type = (AstType *) &basic_type_void;
if (parser->curr->type == Token_Type_Right_Arrow) {
return_type = parse_type(parser);
}
-
- u64 param_count = 0;
- for (AstLocal* param = params;
- param != NULL;
- param = (AstLocal *) param->next)
- param_count++;
-
- AstFunctionType* type_node = bh_alloc(parser->allocator, sizeof(AstFunctionType) + param_count * sizeof(AstType *));
- type_node->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->next) {
- type_node->params[i] = param->type_node;
- i++;
- }
-
- func_def->type_node = (AstType *) type_node;
+ func_def->return_type = return_type;
func_def->body = parse_block(parser);
if (func->scope == NULL)
func->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+ bh_arr_each(AstParam, param, func->params) {
+ if (param->default_value != NULL) {
+ symres_expression(¶m->default_value);
+ if (check_expression(¶m->default_value)) return;
+ }
+ }
+
+ func->return_type = symres_type(func->return_type);
+
scope_enter(func->scope);
- for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->next) {
- param->type_node = symres_type(param->type_node);
- param->type = type_build_from_ast(semstate.allocator, param->type_node);
+ bh_arr_each(AstParam, param, func->params) {
+ if (param->local->type_node != NULL) {
+ param->local->type_node = symres_type(param->local->type_node);
+ param->local->type = type_build_from_ast(semstate.allocator, param->local->type_node);
+
+ if (param->default_value != NULL) {
+ if (!types_are_compatible(param->local->type, param->default_value->type)) {
+ onyx_message_add(Msg_Type_Assignment_Mismatch,
+ param->local->token->pos,
+ type_get_name(param->local->type),
+ type_get_name(param->default_value->type));
+ return;
+ }
+ }
+ } else {
+ param->local->type = param->default_value->type;
+ }
- if (param->type == NULL) break;
+ if (param->local->type == NULL) break;
- symbol_introduce(semstate.curr_scope, param->token, (AstNode *) param);
+ symbol_introduce(semstate.curr_scope, param->local->token, (AstNode *) param->local);
- if (param->flags & Ast_Flag_Param_Use) {
- if (type_is_struct(param->type)) {
+ if (param->local->flags & Ast_Flag_Param_Use) {
+ if (type_is_struct(param->local->type)) {
AstStructType* st;
- if (param->type->kind == Type_Kind_Struct) {
- st = (AstStructType *) param->type_node;
+ if (param->local->type->kind == Type_Kind_Struct) {
+ st = (AstStructType *) param->local->type_node;
} else {
- st = (AstStructType *) ((AstPointerType *) param->type_node)->elem;
+ st = (AstStructType *) ((AstPointerType *) param->local->type_node)->elem;
}
bh_arr_each(AstStructMember *, mem, st->members) {
AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
fa->token = (*mem)->token;
fa->type_node = (*mem)->type_node;
- fa->expr = (AstTyped *) param;
+ fa->expr = (AstTyped *) param->local;
token_toggle_end((*mem)->token);
symbol_raw_introduce(semstate.curr_scope,
(*mem)->token->text,
- param->token->pos,
+ param->local->token->pos,
(AstNode *) fa);
token_toggle_end((*mem)->token);
}
} else {
onyx_message_add(Msg_Type_Literal,
- param->token->pos,
+ param->local->token->pos,
"can only 'use' structures or pointers to structures.");
}
}
}
}
-// NOTE: Kinda hacky way of building the functions type
-Type* type_build_function_type(bh_allocator alloc, AstFunction* func, AstType* return_type) {
- u64 param_count = 0;
- for (AstLocal* param = func->params;
- param != NULL;
- param = (AstLocal *) param->next)
- param_count++;
-
- AstFunctionType* old_ftype = (AstFunctionType *) func->type_node;
+Type* type_build_function_type(bh_allocator alloc, AstFunction* func) {
+ u64 param_count = bh_arr_length(func->params);
+
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, return_type);
+ func_type->Function.needed_param_count = 0;
+ func_type->Function.return_type = type_build_from_ast(alloc, func->return_type);
if (param_count > 0) {
i32 i = 0;
- for (AstLocal* param = func->params;
- param != NULL;
- param = (AstLocal *) param->next) {
- func_type->Function.params[i++] = param->type;
+ bh_arr_each(AstParam, param, func->params) {
+ if (param->default_value == NULL)
+ func_type->Function.needed_param_count++;
+ func_type->Function.params[i++] = param->local->type;
}
}
if (fd->body != NULL) {
// NOTE: Generate the local map
u64 localidx = 0;
- for (AstLocal *param = fd->params; param != NULL; param = (AstLocal *) param->next) {
- if (param->type->kind == Type_Kind_Struct) {
- bh_imap_put(&mod->local_map, (u64) param, localidx | LOCAL_IS_WASM);
- localidx += param->type->Struct.mem_count;
+ bh_arr_each(AstParam, param, fd->params) {
+ if (param->local->type->kind == Type_Kind_Struct) {
+ bh_imap_put(&mod->local_map, (u64) param->local, localidx | LOCAL_IS_WASM);
+ localidx += param->local->type->Struct.mem_count;
} else {
- bh_imap_put(&mod->local_map, (u64) param, localidx++ | LOCAL_IS_WASM);
+ bh_imap_put(&mod->local_map, (u64) param->local, localidx++ | LOCAL_IS_WASM);
}
}