-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcblock.c
More file actions
136 lines (109 loc) · 2.79 KB
/
cblock.c
File metadata and controls
136 lines (109 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "cy.h"
/*
* CBlocks we have
*
* ? cond { then } { else } -- if
* ?? { cond1 { } cond2 { } ... } -- select
* @( list { } -- list loop
* @? cond { } -- cond loop
* -> { } -- call
*
* <- stops the block and makes the owning command evaluate into the value
* <? OP checks the operand to be not NOVALUE and returns it otherwise
*/
static int eval_cblock_end(struct cy_token *t, struct cy_file *f)
{
show_token_err(t, "Dangling cblock terminator");
return -1;
}
static int eval_call(struct cy_token *t, struct cy_file *f)
{
int ret;
struct cy_token ct, mt;
struct cy_value os = { .t = CY_V_NOVALUE };
if (cy_eval_next_x(f, &ct, CY_V_CBLOCK) <= 0)
return -1;
if (cy_eval_next_x(f, &mt, CY_V_MAP) <= 0)
return -1;
if (mt.v.v_map != symbols.v_map) {
os = symbols;
symbols = mt.v;
}
ret = cy_call_cblock(&ct, f, &t->v);
if (os.t != CY_V_NOVALUE)
symbols = os;
if (ret < 0)
return ret;
return 1;
}
static int eval_return(struct cy_token *t, struct cy_file *f)
{
struct cy_token rt;
if (cy_eval_next(f, &rt) <= 0)
return -1;
t->v = rt.v;
return 2;
}
static int eval_value_return(struct cy_token *t, struct cy_file *f)
{
struct cy_token rt;
if (cy_eval_next(f, &rt) <= 0)
return -1;
if (rt.v.t == CY_V_NOVALUE)
return 1;
t->v = rt.v;
return 2;
}
static int eval_novalue_return(struct cy_token *t, struct cy_file *f)
{
struct cy_token rt;
if (cy_eval_next(f, &rt) <= 0)
return -1;
return rt.v.t == CY_V_NOVALUE ? 2 : 1;
}
int cy_call_cblock(struct cy_token *ct, struct cy_file *f, struct cy_value *rv)
{
int ret;
struct cy_cblock *c_list;
struct cy_ctoken *c_nxt;
c_list = f->main;
c_nxt = f->nxt;
init_tokenizer(f, ct->v.v_cblk);
while (1) {
struct cy_token t = {};
ret = cy_eval_next(f, &t);
if (ret == 1) {
if (ct->typ->priv == OP_CBLOCK_SHORT)
ret = 2;
else
continue;
}
if (ret == 0)
ret = 1;
if (ret == 2)
*rv = t.v;
break;
}
f->main = c_list;
f->nxt = c_nxt;
return ret;
}
static struct cy_command cmd_cblock[] = {
{ .name = ".", .t = { .ts = "nop", .priv = OP_CBLOCK_NOP, }, },
{ .name = "{", .t = { .ts = "cblock start", .priv = OP_CBLOCK, }, },
{ .name = "{:", .t = { .ts = "cblock start (short)", .priv = OP_CBLOCK_SHORT, }, },
{ .name = "}", .t = { .ts = "cblock end", .eval = eval_cblock_end, .priv = OP_CBLOCK_END, }, },
{ .name = ":", .t = { .ts = "call", .eval = eval_call, }, },
{ .name = ":=", .t = { .ts = "return", .eval = eval_return, }, },
{ .name = ":+", .t = { .ts = "value return", .eval = eval_value_return, }, },
{ .name = ":-", .t = { .ts = "empty return", .eval = eval_novalue_return, }, },
{}
};
bool is_nop_token(struct cy_token *t)
{
return t->typ->priv == OP_CBLOCK_NOP;
}
void init_cblocks(void)
{
add_commands(cmd_cblock);
}