Skip to content

Commit 3a14fb9

Browse files
committed
added: #inject option to #unquote
1 parent 6f5cdb7 commit 3a14fb9

File tree

5 files changed

+68
-49
lines changed

5 files changed

+68
-49
lines changed

compiler/include/astnodes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,12 @@ struct AstCodeBlock {
16301630
b32 is_expression: 1;
16311631
};
16321632

1633+
typedef struct UnquoteDirectiveBinding UnquoteDirectiveBinding;
1634+
struct UnquoteDirectiveBinding {
1635+
OnyxToken *symbol;
1636+
AstNode *value;
1637+
};
1638+
16331639
struct AstDirectiveInsert {
16341640
AstTyped_base;
16351641

@@ -1638,6 +1644,8 @@ struct AstDirectiveInsert {
16381644

16391645
// Set when using #skip_scope
16401646
AstTyped *skip_scope_index;
1647+
1648+
bh_arr(UnquoteDirectiveBinding) bindings;
16411649
};
16421650

16431651
struct AstDirectiveInit {

compiler/src/checker.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3324,9 +3324,8 @@ CHECK_FUNC(insert_directive, AstDirectiveInsert** pinsert, b32 expected_expressi
33243324
scope_for_cloned_block = scope_create(context, skip_scope, cloned_block->token->pos);
33253325
}
33263326

3327-
if (bound_expr_count > 0) {
3328-
Scope **scope = NULL;
3329-
3327+
Scope **scope = NULL;
3328+
if (bound_expr_count > 0 || bh_arr_length(insert->bindings) > 0) {
33303329
if (cloned_block->kind == Ast_Kind_Block) {
33313330
((AstBlock *) cloned_block)->scope = scope_for_cloned_block;
33323331
scope = &((AstBlock *) cloned_block)->quoted_block_capture_scope;
@@ -3351,26 +3350,35 @@ CHECK_FUNC(insert_directive, AstDirectiveInsert** pinsert, b32 expected_expressi
33513350

33523351
cloned_block = (AstNode *) doblock;
33533352
}
3353+
}
33543354

3355-
if (bound_symbol_count > 0) {
3356-
assert(scope);
3357-
*scope = scope_create(context, NULL, code_block->token->pos);
3355+
if (bound_symbol_count > 0) {
3356+
assert(scope);
3357+
*scope = scope_create(context, NULL, code_block->token->pos);
33583358

3359-
fori (i, 0, bound_symbol_count) {
3360-
CodeBlockBindingSymbol sym = code_block->binding_symbols[i];
3361-
if (sym.type_node) {
3362-
Type *type = type_build_from_ast(context, sym.type_node);
3359+
fori (i, 0, bound_symbol_count) {
3360+
CodeBlockBindingSymbol sym = code_block->binding_symbols[i];
3361+
if (sym.type_node) {
3362+
Type *type = type_build_from_ast(context, sym.type_node);
33633363

3364-
TYPE_CHECK(&insert->binding_exprs[i], type) {
3365-
ERROR_(insert->token->pos, "Expected type '%s' but got type '%s' for the '%d%s' argument to the code block.",
3366-
type_get_name(context, type), type_get_name(context, insert->binding_exprs[i]->type),
3367-
i + 1, bh_num_suffix(i + 1));
3368-
}
3364+
TYPE_CHECK(&insert->binding_exprs[i], type) {
3365+
ERROR_(insert->token->pos, "Expected type '%s' but got type '%s' for the '%d%s' argument to the code block.",
3366+
type_get_name(context, type), type_get_name(context, insert->binding_exprs[i]->type),
3367+
i + 1, bh_num_suffix(i + 1));
33693368
}
3370-
3371-
AstNode *value = (void *) insert->binding_exprs[i];
3372-
symbol_introduce(context, *scope, sym.symbol, value);
33733369
}
3370+
3371+
AstNode *value = (void *) insert->binding_exprs[i];
3372+
symbol_introduce(context, *scope, sym.symbol, value);
3373+
}
3374+
}
3375+
3376+
if (bh_arr_length(insert->bindings) > 0) {
3377+
assert(scope);
3378+
if (!*scope) *scope = scope_create(context, NULL, code_block->token->pos);
3379+
3380+
bh_arr_each(UnquoteDirectiveBinding, binding, insert->bindings) {
3381+
symbol_introduce(context, *scope, binding->symbol, (AstNode *) binding->value);
33743382
}
33753383
}
33763384

compiler/src/parser.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,28 @@ static AstTyped* parse_factor(OnyxParser* parser) {
10781078
insert->skip_scope_index = parse_factor(parser);
10791079
}
10801080

1081+
// CLEANUP: Could this system use the same logic for AstBinding?
1082+
if (parse_possible_directive(parser, "inject")){
1083+
expect_token(parser, '{');
1084+
while (!consume_token_if_next(parser, '}')) {
1085+
if (parser->hit_unexpected_token) break;
1086+
1087+
OnyxToken *sym = expect_token(parser, Token_Type_Symbol);
1088+
expect_token(parser, ':');
1089+
expect_token(parser, ':');
1090+
1091+
AstTyped *binding = parse_top_level_expression(parser);
1092+
1093+
bh_arr_push(insert->bindings, ((UnquoteDirectiveBinding) {
1094+
.symbol = sym,
1095+
.value = (AstNode *) binding
1096+
}));
1097+
1098+
if (parser->curr->type != '}')
1099+
consume_token_if_next(parser, ';');
1100+
}
1101+
}
1102+
10811103
retval = (AstTyped *) insert;
10821104
break;
10831105
}

core/builtin.onyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ __For_Expansion_Flags :: enum #flags {
533533
}
534534

535535
/// All for-loops in Onyx are actually defined as an overload to this procedure.
536-
/// All overloads are macros that accept 3 arguments: the iteratable, flags, and the body
536+
/// All overloads are macros that accept 3 arguments: the iterable, flags, and the body
537537
/// of the loop. Examples of how to use this overloaded procedure can be found in `operations.onyx`
538538
/// next to this file.
539539
__for_expansion :: #match -> void {}

core/container/array.onyx

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,7 @@ Array.filter :: macro (arr: &[..] $T, body: Code) {
306306

307307

308308
#overload #order 100
309-
__for_expansion :: macro (_s: &[..] $T, $flags: __For_Expansion_Flags, $body: Code) where
310-
!(flags & .BY_POINTER)
309+
__for_expansion :: macro (_s: &[..] $T, $flags: __For_Expansion_Flags, $body: Code)
311310
{
312311
__s := _s
313312
__data := __s.data
@@ -317,37 +316,19 @@ __for_expansion :: macro (_s: &[..] $T, $flags: __For_Expansion_Flags, $body: Co
317316
while __i < __count {
318317
defer __i += 1
319318

320-
remove_code :: [] {
321-
Array.delete(__s, __i)
322-
__i -= 1
323-
__count -= 1
319+
#if flags & .BY_POINTER {
320+
v := &__data[__i]
321+
} else {
322+
v := __data[__i]
324323
}
325324

326-
v := __data[__i]
327-
#unquote body(v, __i, remove_code) #skip_scope(1)
328-
}
329-
}
330-
331-
#overload #order 100
332-
__for_expansion :: macro (_s: &[..] $T, $flags: __For_Expansion_Flags, $body: Code) where
333-
(flags & .BY_POINTER)
334-
{
335-
__s := _s
336-
__data := __s.data
337-
__count := __s.count
338-
339-
__i := 0
340-
while __i < __count {
341-
defer __i += 1
342-
343-
remove_code :: [] {
344-
Array.delete(__s, __i)
345-
__i -= 1
346-
__count -= 1
325+
#unquote body(v, __i) #skip_scope(1) #inject {
326+
remove_element :: macro () {
327+
Array.delete(__s, __i)
328+
__i -= 1
329+
__count -= 1
330+
}
347331
}
348-
349-
v := &__data[__i]
350-
#unquote body(v, __i, remove_code) #skip_scope(1)
351332
}
352333
}
353334

0 commit comments

Comments
 (0)