\
NODE(CaptureBlock) \
NODE(CaptureLocal) \
- NODE(CaptureBuilder) \
\
NODE(ForeignBlock) \
\
Ast_Kind_Capture_Block,
Ast_Kind_Capture_Local,
- Ast_Kind_Capture_Builder,
Ast_Kind_Foreign_Block,
Ast_Flag_Binding_Isnt_Captured = BH_BIT(25),
- Ast_Flag_Function_Is_Lambda = BH_BIT(26)
+ Ast_Flag_Function_Is_Lambda = BH_BIT(26),
+ Ast_Flag_Function_Is_Lambda_Inside_PolyProc = BH_BIT(27),
} AstFlags;
typedef enum UnaryOp {
AstBinding *original_binding_to_node;
AstCaptureBlock *captures;
+ Scope *scope_to_lookup_captured_values;
b32 is_exported : 1;
b32 is_foreign : 1;
struct AstCaptureLocal {
AstTyped_base;
- u32 offset;
-};
-
-struct AstCaptureBuilder {
- AstTyped_base;
+ AstTyped *captured_value;
- AstTyped *func;
- AstCaptureBlock *captures;
-
- bh_arr(AstTyped *) capture_values;
+ u32 offset;
};
struct AstPolyQuery {
char *find_closest_symbol_in_scope_and_parents(Scope *scope, char *sym);
char *find_closest_symbol_in_node(AstNode *node, char *sym);
-b32 maybe_create_capture_builder_for_function_expression(AstTyped **pexpr);
-
extern AstTyped node_that_signals_a_yield;
extern AstTyped node_that_signals_failure;
"CAPTURE BLOCK",
"CAPTURE LOCAL",
- "CAPTURE BUILDER",
"FOREIGN BLOCK",
"ZERO VALUE",
node = *pnode;
}
- if (node->kind == Ast_Kind_Function && permanent) {
- if (maybe_create_capture_builder_for_function_expression(pnode)) {
- return TYPE_MATCH_SPECIAL;
- }
- }
-
-
// HACK: NullProcHack
// The null_proc matches any procedure, and because of that, will cause a runtime error if you
// try to call it.
YIELD(expr->token->pos, "Waiting for function type to be resolved.");
expr->flags |= Ast_Flag_Function_Used;
- if (maybe_create_capture_builder_for_function_expression(pexpr)) {
- retval = Check_Return_To_Symres;
- }
break;
case Ast_Kind_Directive_Solidify:
YIELD(expr->token->pos, "Waiting to resolve #this_package.");
break;
- case Ast_Kind_Capture_Builder: {
- AstCaptureBuilder *builder = (void *) expr;
- builder->type = get_expression_type(builder->func);
-
- fori (i, 0, bh_arr_length(builder->capture_values)) {
- if (!builder->captures->captures[i]->type) {
- YIELD(expr->token->pos, "Waiting to know capture value types.");
- }
-
- TYPE_CHECK(&builder->capture_values[i], builder->captures->captures[i]->type) {
- ERROR_(builder->captures->captures[i]->token->pos, "Type mismatch for this captured value. Expected '%s', got '%s'.",
- type_get_name(builder->captures->captures[i]->type), type_get_name(builder->capture_values[i]->type));
- }
- }
+ case Ast_Kind_Capture_Local:
+ expr->type = ((AstCaptureLocal *) expr)->captured_value->type;
break;
- }
case Ast_Kind_File_Contents: break;
case Ast_Kind_Overloaded_Function: break;
case Ast_Kind_Switch_Case: break;
case Ast_Kind_Foreign_Block: break;
case Ast_Kind_Zero_Value: break;
- case Ast_Kind_Capture_Local: break;
default:
retval = Check_Error;
case Ast_Kind_Function:
case Ast_Kind_Polymorphic_Proc: {
- if (clone_depth > 1) {
- clone_depth--;
- return node;
- }
-
AstFunction* df = (AstFunction *) nn;
AstFunction* sf = (AstFunction *) node;
- convert_polyproc_to_function(df);
+ if (clone_depth > 1) {
+ if ((node->flags & Ast_Flag_Function_Is_Lambda) == 0 || !sf->captures) {
+ clone_depth--;
+ return node;
+ }
+ }
+ else {
+ convert_polyproc_to_function(df);
+ }
if (sf->is_foreign) return node;
assert(df->scope == NULL);
df->nodes_that_need_entities_after_clone = NULL;
bh_arr_new(global_heap_allocator, df->nodes_that_need_entities_after_clone, 1);
+
+ bh_arr(AstNode *) old_captured_entities = captured_entities;
captured_entities = df->nodes_that_need_entities_after_clone;
df->return_type = (AstType *) ast_clone(a, sf->return_type);
df->captures = (AstCaptureBlock *) ast_clone(a, sf->captures);
df->nodes_that_need_entities_after_clone = captured_entities;
- captured_entities = NULL;
+ captured_entities = old_captured_entities;
df->params = NULL;
bh_arr_new(context.ast_alloc, df->params, bh_arr_length(sf->params));
}
}
+ if (clone_depth > 1) {
+ sf->flags |= Ast_Flag_Function_Is_Lambda_Inside_PolyProc;
+ df->flags &= ~Ast_Flag_Function_Is_Lambda_Inside_PolyProc;
+ E(df);
+ }
+
break;
}
if (context.options->verbose_output == 3) {
if (ent->expr && ent->expr->token)
snprintf(verbose_output_buffer, 511,
- "%20s | %24s (%d, %d) | %s:%i:%i \n",
+ "%20s | %24s (%d, %d) | %5d | %s:%i:%i \n",
entity_state_strings[ent->state],
entity_type_strings[ent->type],
(u32) ent->macro_attempts,
(u32) ent->micro_attempts,
+ ent->id,
ent->expr->token->pos.filename,
ent->expr->token->pos.line,
ent->expr->token->pos.column);
AstCaptureLocal *capture = make_node(AstCaptureLocal, Ast_Kind_Capture_Local);
capture->token = expect_token(parser, Token_Type_Symbol);
- expect_token(parser, ':');
- capture->type_node = parse_type(parser);
-
bh_arr_push(captures->captures, capture);
if (peek_token(0)->type != end_token)
OnyxToken* symbol;
while (!consume_token_if_next(parser, ')')) {
- if (consume_token_if_next(parser, '|') && !func->captures) {
- func->captures = parse_capture_list(parser, '|');
+ if (consume_token_if_next(parser, '[') && !func->captures) {
+ func->captures = parse_capture_list(parser, ']');
consume_token_if_next(parser, ',');
continue;
}
b32 is_params = (parser->curr + 1) == matching_paren;
OnyxToken* tmp_token = parser->curr;
while (!is_params && tmp_token < matching_paren) {
- if (tmp_token->type == '|') {
- tmp_token++;
- while (tmp_token->type != '|' && tmp_token < matching_paren) {
- tmp_token++;
- }
- tmp_token++;
- }
-
if (tmp_token->type == ':') is_params = 1;
tmp_token++;
}
- if (peek_token(1)->type == '|' && (matching_paren - 1)->type == '|') {
- OnyxToken* tmp_token = parser->curr + 1;
- while (!is_params && tmp_token < matching_paren - 1) {
- if (tmp_token->type == ':') is_params = 1;
- tmp_token++;
- }
+ if (peek_token(1)->type == '[' && (matching_paren - 1)->type == ']') {
+ is_params = 1;
}
return is_params;
while (!consume_token_if_next(parser, ')')) {
if (parser->hit_unexpected_token) return 0;
- if (consume_token_if_next(parser, '|') && !captures) {
- captures = parse_capture_list(parser, '|');
+ if (consume_token_if_next(parser, '[') && !captures) {
+ captures = parse_capture_list(parser, ']');
} else {
QuickParam param = { 0 };
static b32 report_unresolved_symbols = 1;
static b32 resolved_a_symbol = 0;
-// Everything related to waiting on is imcomplete at the moment.
-static Entity* waiting_on = NULL;
-
static Entity* current_entity = NULL;
#define SYMRES(kind, ...) do { \
static SymresStatus symres_macro(AstMacro* macro);
static SymresStatus symres_constraint(AstConstraint* constraint);
static SymresStatus symres_polyquery(AstPolyQuery *query);
-static SymresStatus symres_capture_builder(AstCaptureBuilder *builder);
static void scope_enter(Scope* new_scope) {
current_scope = new_scope;
(*expr)->type_node = builtin_range_type;
break;
+ case Ast_Kind_Polymorphic_Proc:
+ if (((AstFunction *) *expr)->captures) {
+ ((AstFunction *) *expr)->scope_to_lookup_captured_values = current_scope;
+ }
+ break;
+
case Ast_Kind_Function:
+ if (((AstFunction *) *expr)->captures) {
+ ((AstFunction *) *expr)->scope_to_lookup_captured_values = current_scope;
+ }
+
+ SYMRES(type, &(*expr)->type_node);
+ break;
+
case Ast_Kind_NumLit:
SYMRES(type, &(*expr)->type_node);
break;
break;
}
- case Ast_Kind_Capture_Builder: SYMRES(capture_builder, (AstCaptureBuilder *) *expr); break;
-
default: break;
}
return Symres_Success;
}
-static SymresStatus symres_capture_block(AstCaptureBlock *block) {
+static SymresStatus symres_capture_block(AstCaptureBlock *block, Scope *captured_scope) {
bh_arr_each(AstCaptureLocal *, capture, block->captures) {
- SYMRES(type, &(*capture)->type_node);
- }
-
- bh_arr_each(AstCaptureLocal *, capture, block->captures) {
- symbol_introduce(current_scope, (*capture)->token, (AstNode *) *capture);
- }
-
- return Symres_Success;
-}
+ OnyxToken *token = (*capture)->token;
+ AstTyped *resolved = (AstTyped *) symbol_resolve(captured_scope, token);
-static SymresStatus symres_capture_builder(AstCaptureBuilder *builder) {
- fori (i, bh_arr_length(builder->capture_values), bh_arr_length(builder->captures->captures)) {
- OnyxToken *token = builder->captures->captures[i]->token;
- AstTyped *resolved = (AstTyped *) symbol_resolve(current_scope, token);
if (!resolved) {
// Should this do a yield? In there any case that that would make sense?
onyx_report_error(token->pos, Error_Critical, "'%b' is not found in the enclosing scope.",
return Symres_Error;
}
- bh_arr_push(builder->capture_values, resolved);
+ (*capture)->captured_value = resolved;
+ }
+
+ bh_arr_each(AstCaptureLocal *, capture, block->captures) {
+ symbol_introduce(current_scope, (*capture)->token, (AstNode *) *capture);
}
return Symres_Success;
SymresStatus symres_function_header(AstFunction* func) {
func->flags |= Ast_Flag_Comptime;
+ if (func->captures && !func->scope_to_lookup_captured_values) {
+ if (!(func->flags & Ast_Flag_Function_Is_Lambda)) {
+ onyx_report_error(func->captures->token->pos, Error_Critical, "This procedure cannot capture values as it is not defined in an expression.");
+ return Symres_Error;
+ }
+
+ if (func->flags & Ast_Flag_Function_Is_Lambda_Inside_PolyProc) return Symres_Complete;
+
+ return Symres_Yield_Macro;
+ }
+
if (func->scope == NULL)
func->scope = scope_create(context.ast_alloc, current_scope, func->token->pos);
// This makes a lot of assumptions about how these nodes are being processed,
// and I don't want to start using this with other nodes without considering
// what the ramifications of that is.
- assert((*node)->kind == Ast_Kind_Static_If || (*node)->kind == Ast_Kind_File_Contents);
+ assert((*node)->kind == Ast_Kind_Static_If || (*node)->kind == Ast_Kind_File_Contents
+ || (*node)->kind == Ast_Kind_Function || (*node)->kind == Ast_Kind_Polymorphic_Proc);
// Need to current_scope->parent because current_scope is the function body scope.
Scope *scope = current_scope->parent;
}
if (func->captures) {
- if (!(func->flags & Ast_Flag_Function_Is_Lambda)) {
- onyx_report_error(func->captures->token->pos, Error_Critical, "This procedure cannot capture values as it is not defined in an expression.");
- return Symres_Error;
- }
-
- SYMRES(capture_block, func->captures);
+ SYMRES(capture_block, func->captures, func->scope_to_lookup_captured_values);
}
SYMRES(type, &func->return_type);
SymresStatus symres_function(AstFunction* func) {
if (func->entity_header && func->entity_header->state < Entity_State_Check_Types) return Symres_Yield_Macro;
if (func->kind == Ast_Kind_Polymorphic_Proc) return Symres_Complete;
+ if (func->flags & Ast_Flag_Function_Is_Lambda_Inside_PolyProc) return Symres_Complete;
assert(func->scope);
scope_enter(func->scope);
}
-
-b32 maybe_create_capture_builder_for_function_expression(AstTyped **pexpr) {
- AstFunction *func = (void *) *pexpr;
-
- if (!(func->flags & Ast_Flag_Function_Is_Lambda)) return 0;
- if (!func->captures) return 0;
-
- AstCaptureBuilder *builder = onyx_ast_node_new(context.ast_alloc, sizeof(AstCaptureBuilder), Ast_Kind_Capture_Builder);
- builder->token = func->captures->token - 1;
-
- builder->func = (void *) func;
- // builder->type = builder->func->type;
- builder->captures = func->captures;
-
- bh_arr_new(context.ast_alloc, builder->capture_values, bh_arr_length(builder->captures->captures));
-
- *((void **) pexpr) = builder;
- return 1;
-}
-
}
case Ast_Kind_Function: {
- i32 elemidx = get_element_idx(mod, (AstFunction *) expr);
+ AstFunction *func = (AstFunction *) expr;
+ i32 elemidx = get_element_idx(mod, func);
WID(NULL, WI_I32_CONST, elemidx);
- WIL(NULL, WI_I32_CONST, 0);
- break;
- }
-
- case Ast_Kind_Capture_Builder: {
- AstCaptureBuilder *builder = (AstCaptureBuilder *) expr;
-
- assert(builder->func->kind == Ast_Kind_Function);
- i32 elemidx = get_element_idx(mod, (AstFunction *) builder->func);
- WID(NULL, WI_I32_CONST, elemidx);
+ if (!func->captures) {
+ WIL(NULL, WI_I32_CONST, 0);
+ break;
+ }
// Allocate the block
- WIL(NULL, WI_I32_CONST, builder->captures->total_size_in_bytes);
+ WIL(NULL, WI_I32_CONST, func->captures->total_size_in_bytes);
i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) builtin_closure_block_allocate);
WIL(NULL, WI_CALL, func_idx);
WIL(NULL, WI_LOCAL_TEE, capture_block_ptr);
// Populate the block
- fori (i, 0, bh_arr_length(builder->capture_values)) {
+ bh_arr_each(AstCaptureLocal *, capture, func->captures->captures) {
WIL(NULL, WI_LOCAL_GET, capture_block_ptr);
- emit_expression(mod, &code, builder->capture_values[i]);
- emit_store_instruction(mod, &code, builder->capture_values[i]->type, builder->captures->captures[i]->offset);
+ emit_expression(mod, &code, (*capture)->captured_value);
+ emit_store_instruction(mod, &code, (*capture)->captured_value->type, (*capture)->offset);
}
local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
children_of :: (edges: &$T, name: str) -> Iterator(str) {
return iter.concat(
iter.as_iter(edges)
- ->filter((x, |name: str|) => x.a == name)
+ ->filter((x, [name]) => x.a == name)
->map(x => x.b),
iter.as_iter(edges)
- ->filter((x, |name: str|) => x.b == name)
+ ->filter((x, [name]) => x.b == name)
->map(x => x.a)
);
}