typedef struct AstNode AstNode;
typedef struct AstTyped AstTyped;
+typedef struct AstNamedValue AstNamedValue;
typedef struct AstBinaryOp AstBinaryOp;
typedef struct AstUnaryOp AstUnaryOp;
typedef struct AstNumLit AstNumLit;
Ast_Kind_Binary_Op,
Ast_Kind_Compound,
+ Ast_Kind_Named_Value,
Ast_Kind_Type_Start,
Ast_Kind_Type,
struct AstTyped { AstTyped_base; };
// Expression Nodes
+struct AstNamedValue { AstTyped_base; AstNode* value; };
struct AstBinaryOp { AstTyped_base; BinaryOp operation; AstTyped *left, *right; };
struct AstUnaryOp { AstTyped_base; UnaryOp operation; AstTyped *expr; };
struct AstNumLit { AstTyped_base; union { i32 i; i64 l; f32 f; f64 d; } value; };
AstTyped *stnode;
- bh_arr(AstStructMember *) named_values;
+ bh_arr(AstNamedValue *) named_values;
bh_arr(AstTyped *) values;
};
struct AstArrayLiteral {
u64 arg_count;
bh_arr(AstArgument *) arg_arr;
+ bh_arr(AstNamedValue *) named_args; // '.value' is a pointer to AstArgument.
AstTyped *callee;
u64 arg_count;
bh_arr(AstArgument *) arg_arr;
+ bh_arr(AstNamedValue *) named_args;
OnyxIntrinsic intrinsic;
"BIN_OP",
"COMPOUND",
+ "NAMED_VALUE"
"TYPE_START (BAD)",
"TYPE",
bh_arr_zero(sl->values);
StructMember s;
- bh_arr_each(AstStructMember *, smem, sl->named_values) {
- token_toggle_end((*smem)->token);
- if (!type_lookup_member(sl->type, (*smem)->token->text, &s)) {
- onyx_report_error((*smem)->token->pos,
- "The field '%s' does not exist on type '%s'.", (*smem)->token->text, type_get_name(sl->type));
- token_toggle_end((*smem)->token);
+ bh_arr_each(AstNamedValue *, named_value, sl->named_values) {
+ token_toggle_end((*named_value)->token);
+ if (!type_lookup_member(sl->type, (*named_value)->token->text, &s)) {
+ onyx_report_error((*named_value)->token->pos,
+ "The field '%s' does not exist on type '%s'.", (*named_value)->token->text, type_get_name(sl->type));
+ token_toggle_end((*named_value)->token);
return Check_Error;
}
- token_toggle_end((*smem)->token);
+ token_toggle_end((*named_value)->token);
if (s.included_through_use) {
- onyx_report_error((*smem)->token->pos, "Cannot specify value for member '%s', which was included through a 'use' statement.", s.name);
+ onyx_report_error((*named_value)->token->pos, "Cannot specify value for member '%s', which was included through a 'use' statement.", s.name);
return Check_Error;
}
if (sl->values[s.idx] != NULL) {
- onyx_report_error((*smem)->token->pos, "Multiple values given for '%b'.", (*smem)->token->text, (*smem)->token->length);
+ onyx_report_error((*named_value)->token->pos, "Multiple values given for '%b'.", (*named_value)->token->text, (*named_value)->token->length);
return Check_Error;
}
- sl->values[s.idx] = (*smem)->initial_value;
+ sl->values[s.idx] = (AstTyped *) (*named_value)->value;
}
if (sl->type->kind == Type_Kind_Struct) {
bh_arr_new(global_heap_allocator, dt->named_values, bh_arr_length(st->named_values));
bh_arr_new(global_heap_allocator, dt->values, bh_arr_length(st->values));
- bh_arr_each(AstStructMember *, smem, st->named_values)
- bh_arr_push(dt->named_values, (AstStructMember *) ast_clone(a, *smem));
+ bh_arr_each(AstNamedValue *, nv, st->named_values)
+ bh_arr_push(dt->named_values, (AstNamedValue *) ast_clone(a, *nv));
bh_arr_each(AstTyped *, val, st->values)
bh_arr_push(dt->values, (AstTyped *) ast_clone(a, *val));
AstTyped *expr = parse_expression(parser, 0);
if (is_named) {
- AstStructMember* sm = make_node(AstStructMember, Ast_Kind_Struct_Member);
- sm->token = name;
- sm->initial_value = expr;
+ AstNamedValue* nv = make_node(AstStructMember, Ast_Kind_Named_Value);
+ nv->token = name;
+ nv->value = (AstNode *) expr;
- bh_arr_push(sl->named_values, sm);
+ bh_arr_push(sl->named_values, nv);
} else {
bh_arr_push(sl->values, expr);
}
if (sl->named_values != NULL) {
- bh_arr_each(AstStructMember *, smem, sl->named_values) {
- if ((*smem)->initial_value == NULL) onyx_report_error(sl->token->pos, "Some kind of error occured with this struct literal.");
- else symres_expression(&(*smem)->initial_value);
+ bh_arr_each(AstNamedValue *, smem, sl->named_values) {
+ if ((*smem)->value == NULL) onyx_report_error(sl->token->pos, "Some kind of error occured with this struct literal.");
+ else symres_expression((AstTyped **) &(*smem)->value);
}
}
}
if (onyx_has_errors()) return;
}
}
+
+
+static i32 lookup_idx_by_name(AstNode* provider, char* name) {
+ switch (provider->kind) {
+ case Ast_Kind_Struct_Literal: {
+ AstStructLiteral* sl = (AstStructLiteral *) provider;
+ assert(sl->type);
+
+ StructMember s;
+ if (!type_lookup_member(sl->type, name, &s)) return -1; // nocheckin: Report error
+
+ if (s.included_through_use) return -1; // nocheckin: Report error
+
+ return s.idx;
+ }
+
+ case Ast_Kind_Function: {
+ AstFunction* func = (AstFunction *) provider;
+
+ // CLEANUP nocheckin
+ i32 param_idx = -1;
+ i32 idx = 0;
+ bh_arr_each(AstParam, param, func->params) {
+ token_toggle_end(param->local->token);
+
+ if (strncmp(param->local->token->text, name, param->local->token->length) == 0) {
+ param_idx = idx;
+
+ token_toggle_end(param->local->token);
+ break;
+ }
+
+ token_toggle_end(param->local->token);
+
+ idx++;
+ }
+
+ return param_idx;
+ }
+
+ default: return -1;
+ }
+}
+
+static AstNode* lookup_default_value_by_idx(AstNode* provider, i32 idx) {
+ switch (provider->kind) {
+ case Ast_Kind_Struct_Literal: {
+ AstStructLiteral* sl = (AstStructLiteral *) provider;
+ assert(sl->type);
+
+ if (sl->type->kind == Type_Kind_Struct) {
+ bh_arr(StructMember *) memarr = sl->type->Struct.memarr;
+ if (idx >= bh_arr_length(memarr)) return NULL;
+
+ return (AstNode *) *memarr[idx]->initial_value;
+ }
+
+ return NULL;
+ }
+
+ case Ast_Kind_Function: {
+ AstFunction* func = (AstFunction *) provider;
+
+ return (AstNode *) func->params[idx].default_value;
+ }
+
+ default: return NULL;
+ }
+}
+
+// NOTE: The values array can be partially filled out, and is the resulting array.
+// Returns if all the values were filled in.
+b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider) {
+ bh_arr_each(AstNamedValue *, p_named_value, named_values) {
+ AstNamedValue* named_value = *p_named_value;
+
+ token_toggle_end(named_value->token);
+ i32 idx = lookup_idx_by_name(provider, named_value->token->text);
+ if (idx == -1) {
+ onyx_report_error(provider->token->pos,
+ "'%s' is not a valid named parameter here.",
+ named_value->token->text);
+
+ token_toggle_end(named_value->token);
+ return 0;
+ }
+
+ token_toggle_end(named_value->token);
+
+ assert(idx < bh_arr_length(values));
+ values[idx] = named_value->value;
+ }
+
+ fori (idx, 0, bh_arr_length(values)) {
+ if (values[idx] == NULL) {
+ values[idx] = lookup_default_value_by_idx(provider, idx);
+
+ if (values[idx] == NULL) return 0;
+ }
+ }
+
+ return 1;
+}
\ No newline at end of file