b32 invert_condition: 1;
} InterfaceConstraint;
+typedef struct InterfaceVariable {
+ OnyxToken *symbol;
+ AstType *type;
+} InterfaceVariable;
+
struct AstInterface {
AstTyped_base;
char *name;
bh_arr(InterfaceParam) params;
bh_arr(InterfaceConstraint) exprs;
+ bh_arr(InterfaceVariable) vars;
};
typedef enum ConstraintPhase {
CHECK(directive_first, (AstDirectiveFirst *) expr);
break;
+ case Ast_Kind_Constraint_Sentinel:
+ if (expr->type == NULL) YIELD(expr->token->pos, "Waiting to know constraint sentinel's type.");
+ break;
+
case Ast_Kind_StrLit: break;
case Ast_Kind_File_Contents: break;
case Ast_Kind_Overloaded_Function: break;
case Ast_Kind_Package: break;
case Ast_Kind_Error: break;
case Ast_Kind_Unary_Field_Access: break;
- case Ast_Kind_Constraint_Sentinel: break;
case Ast_Kind_Switch_Case: break;
case Ast_Kind_Foreign_Block: break;
case Ast_Kind_Zero_Value: break;
symbol_introduce(constraint->scope, ip->type_token, (AstNode *) type_alias);
}
+ fori (i, 0, bh_arr_length(constraint->interface->vars)) {
+ InterfaceVariable *iv = &constraint->interface->vars[i];
+
+ AstTyped *sentinel = onyx_ast_node_new(context.ast_alloc, sizeof(AstTyped), Ast_Kind_Constraint_Sentinel);
+ sentinel->token = iv->symbol;
+ sentinel->type_node = iv->type;
+
+ symbol_introduce(constraint->scope, iv->symbol, (AstNode *) sentinel);
+ }
+
assert(constraint->entity);
constraint->entity->scope = constraint->scope;
}
bh_arr_new(global_heap_allocator, interface->exprs, 2);
+ bh_arr_new(global_heap_allocator, interface->vars, 2);
expect_token(parser, '{');
while (!consume_token_if_next(parser, '}')) {
if (parser->hit_unexpected_token) return interface;
+ if (parse_possible_directive(parser, "with")) {
+ InterfaceVariable v;
+ v.symbol = expect_token(parser, Token_Type_Symbol);
+ expect_token(parser, ':');
+
+ v.type = parse_type(parser);
+ expect_token(parser, ';');
+
+ bh_arr_push(interface->vars, v);
+ continue;
+ }
+
InterfaceConstraint ic = {0};
if (parse_possible_directive(parser, "not")) {
ic.invert_condition = 1;
}
switch ((*expr)->kind) {
- case Ast_Kind_Symbol: SYMRES(symbol, (AstNode **) expr); break;
+ case Ast_Kind_Symbol:
+ SYMRES(symbol, (AstNode **) expr);
+
+ // HACK?
+ // I don't know how I never ran into this problem before,
+ // but when a symbol is resolved, there is never a "double
+ // check" that its type node is symbol resolved as well.
+ // This only proved to be an issue when using constraint
+ // sentinels, so I only added that case here. This should
+ // maybe be considered in the future because I think this
+ // lack of double checking could be causing other bugs.
+ if ((*expr)->kind == Ast_Kind_Constraint_Sentinel) {
+ SYMRES(type, &(*expr)->type_node);
+ }
+ break;
case Ast_Kind_Binary_Op:
SYMRES(expression, &((AstBinaryOp *)(*expr))->left);
}
break;
+ case Ast_Kind_Constraint_Sentinel: {
+ AstTyped *sentinel = (AstTyped *) *expr;
+ SYMRES(type, &sentinel->type_node);
+ break;
+ }
+
default: break;
}