|
@@ -345,6 +345,7 @@ typedef struct {
|
|
T_BANG,
|
|
T_BANG,
|
|
T_RAISE,
|
|
T_RAISE,
|
|
T_TILDE,
|
|
T_TILDE,
|
|
|
|
+ T_AT,
|
|
|
|
|
|
T_INLINE,
|
|
T_INLINE,
|
|
T_HEADER,
|
|
T_HEADER,
|
|
@@ -723,6 +724,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
return TK(RAISE);
|
|
return TK(RAISE);
|
|
else if (source[*pos] == '~' && ++(*pos))
|
|
else if (source[*pos] == '~' && ++(*pos))
|
|
return TK(TILDE);
|
|
return TK(TILDE);
|
|
|
|
+ else if (source[*pos] == '@' && ++(*pos))
|
|
|
|
+ return TK(AT);
|
|
|
|
|
|
LEX_ERROR("unexpected input")
|
|
LEX_ERROR("unexpected input")
|
|
}
|
|
}
|
|
@@ -814,7 +817,6 @@ struct _node_t {
|
|
N_LET,
|
|
N_LET,
|
|
N_VARUNPACK,
|
|
N_VARUNPACK,
|
|
N_LETUNPACK,
|
|
N_LETUNPACK,
|
|
- N_UNPACK,
|
|
|
|
N_CONST,
|
|
N_CONST,
|
|
N_IF,
|
|
N_IF,
|
|
N_SWITCH,
|
|
N_SWITCH,
|
|
@@ -857,6 +859,7 @@ struct _node_t {
|
|
table_t *h2;
|
|
table_t *h2;
|
|
|
|
|
|
token_t *t;
|
|
token_t *t;
|
|
|
|
+ token_t *t2;
|
|
|
|
|
|
size_t fi;
|
|
size_t fi;
|
|
size_t pos;
|
|
size_t pos;
|
|
@@ -1039,6 +1042,10 @@ node_t *nodef(int tag, token_t *name, table_t *params, table_t *captured, node_t
|
|
|
|
|
|
#define NODEF(n, a, b, c, d) (node_pos(nodef(N_##n, (a), (b), (c), (d)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
|
|
#define NODEF(n, a, b, c, d) (node_pos(nodef(N_##n, (a), (b), (c), (d)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
|
|
|
|
|
|
|
|
+#define LABELLOOP(n)\
|
|
|
|
+ node_t *ln = (n);\
|
|
|
|
+ ln->t2 = label;
|
|
|
|
+
|
|
#define AT(tk) (*pos < tokens->length && ((token_t *)tokens->data[*pos])->tag == T_##tk)
|
|
#define AT(tk) (*pos < tokens->length && ((token_t *)tokens->data[*pos])->tag == T_##tk)
|
|
#define ATP(tk, p) ((*pos)+p < tokens->length && ((token_t *)tokens->data[(*pos)+p])->tag == T_##tk)
|
|
#define ATP(tk, p) ((*pos)+p < tokens->length && ((token_t *)tokens->data[(*pos)+p])->tag == T_##tk)
|
|
#define MATCH(tk) (AT(tk) && ++(*pos))
|
|
#define MATCH(tk) (AT(tk) && ++(*pos))
|
|
@@ -1580,7 +1587,7 @@ node_t *parse_var(list_t *tokens, size_t *pos, int is_let) {
|
|
}
|
|
}
|
|
|
|
|
|
node_t *parse_unpack(list_t *tokens, size_t *pos, int tag) {
|
|
node_t *parse_unpack(list_t *tokens, size_t *pos, int tag) {
|
|
- EXPECT(LPAR, "(");
|
|
|
|
|
|
+ EXPECT(LSB, "[");
|
|
|
|
|
|
list_t *l = list_new();
|
|
list_t *l = list_new();
|
|
|
|
|
|
@@ -1591,17 +1598,15 @@ node_t *parse_unpack(list_t *tokens, size_t *pos, int tag) {
|
|
list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
} while (MATCH(COMMA));
|
|
} while (MATCH(COMMA));
|
|
|
|
|
|
- EXPECT(RPAR, ")");
|
|
|
|
|
|
+ EXPECT(RSB, "]");
|
|
EXPECT(ASSIGN, "=");
|
|
EXPECT(ASSIGN, "=");
|
|
|
|
|
|
node_t *a = parse_expr(tokens, pos);
|
|
node_t *a = parse_expr(tokens, pos);
|
|
|
|
|
|
- if (tag == N_VARUNPACK)
|
|
|
|
- return NODE1l(VARUNPACK, a, l);
|
|
|
|
- else if (tag == N_LETUNPACK)
|
|
|
|
|
|
+ if (tag == N_LETUNPACK)
|
|
return NODE1l(LETUNPACK, a, l);
|
|
return NODE1l(LETUNPACK, a, l);
|
|
|
|
|
|
- return NODE1l(UNPACK, a, l);
|
|
|
|
|
|
+ return NODE1l(VARUNPACK, a, l);
|
|
}
|
|
}
|
|
|
|
|
|
node_t *parse_func(list_t *tokens, size_t *pos, int is_expr) {
|
|
node_t *parse_func(list_t *tokens, size_t *pos, int is_expr) {
|
|
@@ -1705,18 +1710,16 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
|
|
|
|
return NODEL(BLOCK, stmts);
|
|
return NODEL(BLOCK, stmts);
|
|
} else if (MATCH(VAR)) {
|
|
} else if (MATCH(VAR)) {
|
|
- if (AT(LPAR))
|
|
|
|
|
|
+ if (AT(LSB))
|
|
return parse_unpack(tokens, pos, N_VARUNPACK);
|
|
return parse_unpack(tokens, pos, N_VARUNPACK);
|
|
|
|
|
|
return parse_var(tokens, pos, 0);
|
|
return parse_var(tokens, pos, 0);
|
|
} else if (MATCH(LET)) {
|
|
} else if (MATCH(LET)) {
|
|
- if (AT(LPAR))
|
|
|
|
|
|
+ if (AT(LSB))
|
|
return parse_unpack(tokens, pos, N_LETUNPACK);
|
|
return parse_unpack(tokens, pos, N_LETUNPACK);
|
|
|
|
|
|
return parse_var(tokens, pos, 1);
|
|
return parse_var(tokens, pos, 1);
|
|
- } else if (MATCH(UNPACK))
|
|
|
|
- return parse_unpack(tokens, pos, N_UNPACK);
|
|
|
|
- else if (MATCH(CONST)) {
|
|
|
|
|
|
+ } else if (MATCH(CONST)) {
|
|
table_t *h = table_new();
|
|
table_t *h = table_new();
|
|
|
|
|
|
do {
|
|
do {
|
|
@@ -1742,6 +1745,15 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
} else if (MATCH(IF))
|
|
} else if (MATCH(IF))
|
|
return parse_if(tokens, pos);
|
|
return parse_if(tokens, pos);
|
|
else if (MATCH(SWITCH)) {
|
|
else if (MATCH(SWITCH)) {
|
|
|
|
+ token_t *label = NULL;
|
|
|
|
+
|
|
|
|
+ if (MATCH(AT)) {
|
|
|
|
+ if(!AT(NAME))
|
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
|
+
|
|
|
|
+ label = tokens->data[(*pos)++];
|
|
|
|
+ }
|
|
|
|
+
|
|
node_t *a = parse_expr(tokens, pos);
|
|
node_t *a = parse_expr(tokens, pos);
|
|
|
|
|
|
EXPECT(LCB, "{");
|
|
EXPECT(LCB, "{");
|
|
@@ -1787,14 +1799,25 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
if (!cases->length && !b)
|
|
if (!cases->length && !b)
|
|
PARSE_ERROR("empty switch statement");
|
|
PARSE_ERROR("empty switch statement");
|
|
|
|
|
|
- return NODE2l(SWITCH, a, b, cases);
|
|
|
|
|
|
+ LABELLOOP(NODE2l(SWITCH, a, b, cases));
|
|
|
|
+
|
|
|
|
+ return ln;
|
|
} else if (MATCH(FOR)) {
|
|
} else if (MATCH(FOR)) {
|
|
|
|
+ token_t *label = NULL;
|
|
|
|
+
|
|
|
|
+ if (MATCH(AT)) {
|
|
|
|
+ if(!AT(NAME))
|
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
|
+
|
|
|
|
+ label = tokens->data[(*pos)++];
|
|
|
|
+ }
|
|
|
|
+
|
|
node_t *a = NULL;
|
|
node_t *a = NULL;
|
|
node_t *b = NULL;
|
|
node_t *b = NULL;
|
|
node_t *c = NULL;
|
|
node_t *c = NULL;
|
|
|
|
|
|
if (!AT(LCB) && !AT(COLON) && !CLIFF) {
|
|
if (!AT(LCB) && !AT(COLON) && !CLIFF) {
|
|
- if (MATCH(LPAR)) {
|
|
|
|
|
|
+ if (MATCH(LSB)) {
|
|
list_t *l = list_new();
|
|
list_t *l = list_new();
|
|
|
|
|
|
do {
|
|
do {
|
|
@@ -1804,13 +1827,15 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
} while (MATCH(COMMA));
|
|
} while (MATCH(COMMA));
|
|
|
|
|
|
- EXPECT(RPAR, ")");
|
|
|
|
|
|
+ EXPECT(RSB, "]");
|
|
EXPECT(OF, "of");
|
|
EXPECT(OF, "of");
|
|
|
|
|
|
a = parse_expr(tokens, pos);
|
|
a = parse_expr(tokens, pos);
|
|
b = BLOCK();
|
|
b = BLOCK();
|
|
|
|
|
|
- return NODE2l(FOROFUNPACK, a, b, l);
|
|
|
|
|
|
+ LABELLOOP(NODE2l(FOROFUNPACK, a, b, l));
|
|
|
|
+
|
|
|
|
+ return ln;
|
|
}
|
|
}
|
|
|
|
|
|
if (AT(NAME) && ATP(OF, 1)) {
|
|
if (AT(NAME) && ATP(OF, 1)) {
|
|
@@ -1821,11 +1846,13 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
a = parse_expr(tokens, pos);
|
|
a = parse_expr(tokens, pos);
|
|
b = BLOCK();
|
|
b = BLOCK();
|
|
|
|
|
|
- return NODE2t(FOROF, a, b, t);
|
|
|
|
|
|
+ LABELLOOP(NODE2t(FOROF, a, b, t));
|
|
|
|
+
|
|
|
|
+ return ln;
|
|
}
|
|
}
|
|
|
|
|
|
if (MATCH(VAR)) {
|
|
if (MATCH(VAR)) {
|
|
- if (MATCH(LPAR)) {
|
|
|
|
|
|
+ if (MATCH(LSB)) {
|
|
list_t *l = list_new();
|
|
list_t *l = list_new();
|
|
|
|
|
|
do {
|
|
do {
|
|
@@ -1835,13 +1862,15 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
} while (MATCH(COMMA));
|
|
} while (MATCH(COMMA));
|
|
|
|
|
|
- EXPECT(RPAR, ")");
|
|
|
|
|
|
+ EXPECT(RCB, "]");
|
|
EXPECT(OF, "of");
|
|
EXPECT(OF, "of");
|
|
|
|
|
|
a = parse_expr(tokens, pos);
|
|
a = parse_expr(tokens, pos);
|
|
b = BLOCK();
|
|
b = BLOCK();
|
|
|
|
|
|
- return NODE2l(FOROFVARUNPACK, a, b, l);
|
|
|
|
|
|
+ LABELLOOP(NODE2l(FOROFVARUNPACK, a, b, l));
|
|
|
|
+
|
|
|
|
+ return ln;
|
|
}
|
|
}
|
|
|
|
|
|
if (AT(NAME) && ATP(OF, 1)) {
|
|
if (AT(NAME) && ATP(OF, 1)) {
|
|
@@ -1852,7 +1881,9 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
a = parse_expr(tokens, pos);
|
|
a = parse_expr(tokens, pos);
|
|
b = BLOCK();
|
|
b = BLOCK();
|
|
|
|
|
|
- return NODE2t(FOROFVAR, a, b, t);
|
|
|
|
|
|
+ LABELLOOP(NODE2t(FOROFVAR, a, b, t));
|
|
|
|
+
|
|
|
|
+ return ln;
|
|
}
|
|
}
|
|
|
|
|
|
a = parse_var(tokens, pos, 0);
|
|
a = parse_var(tokens, pos, 0);
|
|
@@ -1865,14 +1896,16 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
|
|
|
|
node_t *d = BLOCK();
|
|
node_t *d = BLOCK();
|
|
|
|
|
|
- return NODE4(FOR, a, b, c, d);
|
|
|
|
|
|
+ LABELLOOP(NODE4(FOR, a, b, c, d));
|
|
|
|
+
|
|
|
|
+ return ln;
|
|
} else if (MATCH(BREAK)) {
|
|
} else if (MATCH(BREAK)) {
|
|
- if (AT(NUMBER) && !CLIFF)
|
|
|
|
|
|
+ if ((AT(NUMBER) || AT(NAME)) && !CLIFF)
|
|
return NODET(BREAK, tokens->data[(*pos)++]);
|
|
return NODET(BREAK, tokens->data[(*pos)++]);
|
|
|
|
|
|
return NODE0(BREAK);
|
|
return NODE0(BREAK);
|
|
} else if (MATCH(CONTINUE)) {
|
|
} else if (MATCH(CONTINUE)) {
|
|
- if (AT(NUMBER) && !CLIFF)
|
|
|
|
|
|
+ if ((AT(NUMBER) || AT(NAME)) && !CLIFF)
|
|
return NODET(CONTINUE, tokens->data[(*pos)++]);
|
|
return NODET(CONTINUE, tokens->data[(*pos)++]);
|
|
|
|
|
|
return NODE0(CONTINUE);
|
|
return NODE0(CONTINUE);
|
|
@@ -2048,33 +2081,34 @@ node_t *parse(char *source) {
|
|
#define NEWGID() size_t gid = GID++
|
|
#define NEWGID() size_t gid = GID++
|
|
|
|
|
|
#define EMIT(fmt, ...) buffer_fmt(buf, (fmt), ##__VA_ARGS__);
|
|
#define EMIT(fmt, ...) buffer_fmt(buf, (fmt), ##__VA_ARGS__);
|
|
-#define BINOP(s) { EMIT("qi_" s "(state, "); compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a); EMIT(", "); compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b); EMIT(")"); }
|
|
|
|
-#define UNOP(s) { EMIT("qi_" s "(state, "); compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a); EMIT(")"); }
|
|
|
|
-#define ASSIGN(lhs, rhs) {\
|
|
|
|
|
|
+#define BINOP(s) { EMIT("qi_" s "(state, "); compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a); EMIT(", "); compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b); EMIT(")"); }
|
|
|
|
+#define UNOP(s) { EMIT("qi_" s "(state, "); compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a); EMIT(")"); }
|
|
|
|
+#define ASSIGNIN(buf, lhs, rhs) {\
|
|
if ((lhs)->tag == N_LITERAL && (lhs)->t->tag == T_NAME) {\
|
|
if ((lhs)->tag == N_LITERAL && (lhs)->t->tag == T_NAME) {\
|
|
- EMIT("qi_set(state, false, \"%s\", ", (lhs)->t->text);\
|
|
|
|
|
|
+ buffer_fmt(buf, "qi_set(state, false, \"%s\", ", (lhs)->t->text);\
|
|
rhs;\
|
|
rhs;\
|
|
- EMIT(")");\
|
|
|
|
|
|
+ buffer_fmt(buf, ")");\
|
|
} else if ((lhs)->tag == N_INDEX) {\
|
|
} else if ((lhs)->tag == N_INDEX) {\
|
|
- EMIT("qi_index_set(state, false, ");\
|
|
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, (lhs)->a);\
|
|
|
|
- EMIT(", ");\
|
|
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, (lhs)->b);\
|
|
|
|
- EMIT(", ");\
|
|
|
|
|
|
+ buffer_fmt(buf, "qi_index_set(state, false, ");\
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a);\
|
|
|
|
+ buffer_fmt(buf, ", ");\
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->b);\
|
|
|
|
+ buffer_fmt(buf, ", ");\
|
|
rhs;\
|
|
rhs;\
|
|
- EMIT(")");\
|
|
|
|
|
|
+ buffer_fmt(buf, ")");\
|
|
} else if ((lhs)->tag == N_MEMBER) {\
|
|
} else if ((lhs)->tag == N_MEMBER) {\
|
|
- EMIT("qi_index_set(state, false, ");\
|
|
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, (lhs)->a);\
|
|
|
|
- EMIT(", qi_make_string(state, \"%s\"), ", (lhs)->t->text);\
|
|
|
|
|
|
+ buffer_fmt(buf, "qi_index_set(state, false, ");\
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a);\
|
|
|
|
+ buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text);\
|
|
rhs;\
|
|
rhs;\
|
|
- EMIT(")");\
|
|
|
|
|
|
+ buffer_fmt(buf, ")");\
|
|
} else COMPILE_ERROR("illegal assignment left-hand side");\
|
|
} else COMPILE_ERROR("illegal assignment left-hand side");\
|
|
}
|
|
}
|
|
|
|
+#define ASSIGN(lhs, rhs) ASSIGNIN(buf, lhs, rhs)
|
|
#define COMPASSIGN(lhs, s, rhs) {\
|
|
#define COMPASSIGN(lhs, s, rhs) {\
|
|
ASSIGN(node->a, {\
|
|
ASSIGN(node->a, {\
|
|
EMIT("qi_%s(state, ", s);\
|
|
EMIT("qi_%s(state, ", s);\
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, (lhs));\
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs));\
|
|
EMIT(", ");\
|
|
EMIT(", ");\
|
|
rhs;\
|
|
rhs;\
|
|
EMIT(")");\
|
|
EMIT(")");\
|
|
@@ -2082,9 +2116,9 @@ node_t *parse(char *source) {
|
|
}
|
|
}
|
|
#define COMPILE_ERROR(fmt, ...) { format_error(GETFNAME(node->fi), GETSRC(node->fi), node->pos, fmt, ##__VA_ARGS__); exit(1); }
|
|
#define COMPILE_ERROR(fmt, ...) { format_error(GETFNAME(node->fi), GETSRC(node->fi), node->pos, fmt, ##__VA_ARGS__); exit(1); }
|
|
|
|
|
|
-void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node);
|
|
|
|
|
|
+void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node);
|
|
|
|
|
|
-void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, list_t *seq) {
|
|
|
|
|
|
+void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, list_t *seq) {
|
|
if (!seq || seq->length < 1) {
|
|
if (!seq || seq->length < 1) {
|
|
EMIT("NULL");
|
|
EMIT("NULL");
|
|
|
|
|
|
@@ -2101,7 +2135,7 @@ void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
for (size_t i = 0; i < seq->length; i++) {
|
|
for (size_t i = 0; i < seq->length; i++) {
|
|
buffer_fmt(tbuf, "qi_list_data(list, %d) = ", i);
|
|
buffer_fmt(tbuf, "qi_list_data(list, %d) = ", i);
|
|
|
|
|
|
- compile_node(gbuf, tbuf, ctx, lstk, sstk, lbl, seq->data[i]);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, seq->data[i]);
|
|
|
|
|
|
buffer_fmt(tbuf, ";\n");
|
|
buffer_fmt(tbuf, ";\n");
|
|
}
|
|
}
|
|
@@ -2114,7 +2148,7 @@ void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
EMIT("__list%d(state)", gid);
|
|
EMIT("__list%d(state)", gid);
|
|
}
|
|
}
|
|
|
|
|
|
-void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, table_t *table) {
|
|
|
|
|
|
+void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, table_t *table) {
|
|
if (!table || table->used < 1) {
|
|
if (!table || table->used < 1) {
|
|
EMIT("NULL");
|
|
EMIT("NULL");
|
|
|
|
|
|
@@ -2131,7 +2165,7 @@ void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, st
|
|
table_iterate(table, {
|
|
table_iterate(table, {
|
|
buffer_fmt(tbuf, "qi_table_set(table, \"%s\", ", entry.key);
|
|
buffer_fmt(tbuf, "qi_table_set(table, \"%s\", ", entry.key);
|
|
|
|
|
|
- compile_node(gbuf, tbuf, ctx, lstk, sstk, lbl, entry.value);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, entry.value);
|
|
|
|
|
|
buffer_fmt(tbuf, ");\n");
|
|
buffer_fmt(tbuf, ");\n");
|
|
});
|
|
});
|
|
@@ -2215,7 +2249,7 @@ char *tempvar() {
|
|
return s;
|
|
return s;
|
|
}
|
|
}
|
|
|
|
|
|
-void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node, char *name) {
|
|
|
|
|
|
+void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node, char *name) {
|
|
NEWGID();
|
|
NEWGID();
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
buffer_t *tbuf = buffer_new();
|
|
@@ -2238,7 +2272,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
optargc++;
|
|
optargc++;
|
|
|
|
|
|
buffer_fmt(tbuf, "qi_decl(state, \"%s\", pargc >= %d? qi_list_index(pargs, %d): ", entry.key, argc+1, argc);
|
|
buffer_fmt(tbuf, "qi_decl(state, \"%s\", pargc >= %d? qi_list_index(pargs, %d): ", entry.key, argc+1, argc);
|
|
- compile_node(gbuf, tbuf, ctx, lstk, sstk, lbl, pair->data[1]);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, pair->data[1]);
|
|
buffer_fmt(tbuf, ");\n");
|
|
buffer_fmt(tbuf, ");\n");
|
|
} else
|
|
} else
|
|
buffer_fmt(tbuf, "qi_decl(state, \"%s\", qi_list_index(pargs, %d));\n", entry.key, argc);
|
|
buffer_fmt(tbuf, "qi_decl(state, \"%s\", qi_list_index(pargs, %d));\n", entry.key, argc);
|
|
@@ -2247,7 +2281,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
- compile_node(gbuf, tbuf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
CTXPOP();
|
|
CTXPOP();
|
|
CTXPOP();
|
|
CTXPOP();
|
|
@@ -2261,7 +2295,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
tbuf = buffer_new();
|
|
tbuf = buffer_new();
|
|
|
|
|
|
buffer_fmt(tbuf, "qi_make_function(state, \"%s\", %d, __func%d, ", name? name: node->t? node->t->text: "<anon>", !node->h? 0: (node->h->used - optargc), gid);
|
|
buffer_fmt(tbuf, "qi_make_function(state, \"%s\", %d, __func%d, ", name? name: node->t? node->t->text: "<anon>", !node->h? 0: (node->h->used - optargc), gid);
|
|
- compile_table(gbuf, tbuf, ctx, lstk, sstk, lbl, node->h2);
|
|
|
|
|
|
+ compile_table(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->h2);
|
|
buffer_fmt(tbuf, ")");
|
|
buffer_fmt(tbuf, ")");
|
|
|
|
|
|
if (node->tag == N_FUNCEXPR) {
|
|
if (node->tag == N_FUNCEXPR) {
|
|
@@ -2277,7 +2311,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
table_t *CONSTANTS;
|
|
table_t *CONSTANTS;
|
|
|
|
|
|
-void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, list_t *block, int toplevel) {
|
|
|
|
|
|
+void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, list_t *block, int toplevel) {
|
|
for (size_t i = 0; i < block->length; i++) {
|
|
for (size_t i = 0; i < block->length; i++) {
|
|
node_t *node = block->data[i];
|
|
node_t *node = block->data[i];
|
|
|
|
|
|
@@ -2294,7 +2328,7 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, st
|
|
table_set(CONSTANTS, name, entry.value);
|
|
table_set(CONSTANTS, name, entry.value);
|
|
});
|
|
});
|
|
} else if (node->tag == N_FUNCDEF) {
|
|
} else if (node->tag == N_FUNCDEF) {
|
|
- compile_func(gbuf, buf, ctx, lstk, sstk, lbl, node, NULL);
|
|
|
|
|
|
+ compile_func(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, NULL);
|
|
|
|
|
|
EMIT("\n");
|
|
EMIT("\n");
|
|
} else if (node->tag == N_CLASS) {
|
|
} else if (node->tag == N_CLASS) {
|
|
@@ -2328,9 +2362,9 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, st
|
|
|
|
|
|
buffer_fmt(tbuf, "qi_table_set(%s, \"%s\", ", triple->data[1] != NULL? "table": "metatable", t->text);
|
|
buffer_fmt(tbuf, "qi_table_set(%s, \"%s\", ", triple->data[1] != NULL? "table": "metatable", t->text);
|
|
if (triple->data[1] == NULL)
|
|
if (triple->data[1] == NULL)
|
|
- compile_func(gbuf, tbuf, ctx, lstk, sstk, lbl, triple->data[2], buffer_read(methodname));
|
|
|
|
|
|
+ compile_func(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, triple->data[2], buffer_read(methodname));
|
|
else
|
|
else
|
|
- compile_node(gbuf, tbuf, ctx, lstk, sstk, lbl, triple->data[2]);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, triple->data[2]);
|
|
buffer_fmt(tbuf, ");\n");
|
|
buffer_fmt(tbuf, ");\n");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2366,7 +2400,7 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, st
|
|
if (n->tag == N_FUNCDEF)
|
|
if (n->tag == N_FUNCDEF)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, n);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
|
|
|
|
|
|
EMIT("\n");
|
|
EMIT("\n");
|
|
}
|
|
}
|
|
@@ -3037,6 +3071,7 @@ const char *STD[][2] = {
|
|
},
|
|
},
|
|
|
|
|
|
{"time",
|
|
{"time",
|
|
|
|
+ "header `#include <time.h>`\n"
|
|
"func time() {\n"
|
|
"func time() {\n"
|
|
" inline `unsigned long long ts = time(NULL)`\n"
|
|
" inline `unsigned long long ts = time(NULL)`\n"
|
|
" inline `return qi_make_number(state, ts)`\n"
|
|
" inline `return qi_make_number(state, ts)`\n"
|
|
@@ -3164,9 +3199,9 @@ char *unescape(char *s) {
|
|
return buffer_read(buf);
|
|
return buffer_read(buf);
|
|
}
|
|
}
|
|
|
|
|
|
-void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl);
|
|
|
|
|
|
+void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl);
|
|
|
|
|
|
-int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, char *path) {
|
|
|
|
|
|
+int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, char *path) {
|
|
char *source = NULL;
|
|
char *source = NULL;
|
|
|
|
|
|
for (size_t i = 0; STD[i][0]; i++) {
|
|
for (size_t i = 0; STD[i][0]; i++) {
|
|
@@ -3206,7 +3241,7 @@ int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stac
|
|
|
|
|
|
list_push(FILES, pair);
|
|
list_push(FILES, pair);
|
|
|
|
|
|
- compile_into(source, gbuf, buf, ctx, lstk, sstk, lbl);
|
|
|
|
|
|
+ compile_into(source, gbuf, buf, ctx, ltab, lstk, sstk, lbl);
|
|
|
|
|
|
list_pop(FILES);
|
|
list_pop(FILES);
|
|
list_push(REQUIRED, path);
|
|
list_push(REQUIRED, path);
|
|
@@ -3216,15 +3251,15 @@ int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stac
|
|
|
|
|
|
buffer_t *HBUF;
|
|
buffer_t *HBUF;
|
|
|
|
|
|
-void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node) {
|
|
|
|
|
|
+void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node) {
|
|
switch (node->tag) {
|
|
switch (node->tag) {
|
|
case N_TOPLEVEL: case N_PROGRAM:
|
|
case N_TOPLEVEL: case N_PROGRAM:
|
|
- compile_block(gbuf, buf, ctx, lstk, sstk, lbl, node->l, node->tag == N_TOPLEVEL);
|
|
|
|
|
|
+ compile_block(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l, node->tag == N_TOPLEVEL);
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_EXPRSTMT:
|
|
case N_EXPRSTMT:
|
|
EMIT("(void)(");
|
|
EMIT("(void)(");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(");");
|
|
EMIT(");");
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -3232,7 +3267,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
LBPUSH();
|
|
LBPUSH();
|
|
CTXPUSH("scope");
|
|
CTXPUSH("scope");
|
|
EMIT("qi_new_scope(state);\n");
|
|
EMIT("qi_new_scope(state);\n");
|
|
- compile_block(gbuf, buf, ctx, lstk, sstk, lbl, node->l, 0);
|
|
|
|
|
|
+ compile_block(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l, 0);
|
|
EMIT("qi_old_scope(state);");
|
|
EMIT("qi_old_scope(state);");
|
|
CTXPOP();
|
|
CTXPOP();
|
|
LBPOP();
|
|
LBPOP();
|
|
@@ -3277,7 +3312,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
node_t *n = table_get(CONSTANTS, name);
|
|
node_t *n = table_get(CONSTANTS, name);
|
|
|
|
|
|
if (n)
|
|
if (n)
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, n);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
|
|
else
|
|
else
|
|
EMIT("qi_get(state, \"%s\")", name);
|
|
EMIT("qi_get(state, \"%s\")", name);
|
|
} break;
|
|
} break;
|
|
@@ -3289,13 +3324,13 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
case N_LIST:
|
|
case N_LIST:
|
|
EMIT("qi_make_list(state, ");
|
|
EMIT("qi_make_list(state, ");
|
|
- compile_list(gbuf, buf, ctx, lstk, sstk, lbl, node->l);
|
|
|
|
|
|
+ compile_list(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l);
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_TUPLE:
|
|
case N_TUPLE:
|
|
EMIT("qi_make_tuple(state, ");
|
|
EMIT("qi_make_tuple(state, ");
|
|
- compile_list(gbuf, buf, ctx, lstk, sstk, lbl, node->l);
|
|
|
|
|
|
+ compile_list(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l);
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -3303,43 +3338,113 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
case N_TABLE:
|
|
case N_TABLE:
|
|
EMIT("qi_make_table(state, ");
|
|
EMIT("qi_make_table(state, ");
|
|
- compile_table(gbuf, buf, ctx, lstk, sstk, lbl, node->h);
|
|
|
|
|
|
+ compile_table(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->h);
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_CALL:
|
|
case N_CALL:
|
|
EMIT("qi_call(state, ");
|
|
EMIT("qi_call(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(", ");
|
|
EMIT(", ");
|
|
- compile_list(gbuf, buf, ctx, lstk, sstk, lbl, node->l);
|
|
|
|
|
|
+ compile_list(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l);
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_MEMBER:
|
|
case N_MEMBER:
|
|
EMIT("qi_index(state, ");
|
|
EMIT("qi_index(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(", qi_make_string(state, \"%s\"))", node->t->text);
|
|
EMIT(", qi_make_string(state, \"%s\"))", node->t->text);
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_INDEX:
|
|
case N_INDEX:
|
|
EMIT("qi_index(state, ");
|
|
EMIT("qi_index(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(", ");
|
|
EMIT(", ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
- case N_ASSIGN: ASSIGN(node->a, compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
|
|
+ case N_ASSIGN:
|
|
|
|
+ if (node->a->tag == N_LIST) {
|
|
|
|
+ if (node->a->l->length < 2)
|
|
|
|
+ COMPILE_ERROR("illegal unpack assignment left-hand side");
|
|
|
|
+
|
|
|
|
+ NEWGID();
|
|
|
|
+
|
|
|
|
+ buffer_t *tbuf = buffer_new();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "inline static qi_value_t *__assign%d(qi_state_t *state) {\n", gid);
|
|
|
|
+
|
|
|
|
+ char *varname = tempvar();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *%s = ", varname);
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+
|
|
|
|
+ for (size_t i = 0; i < node->a->l->length; i++) {
|
|
|
|
+ ASSIGNIN(tbuf, (node_t *)node->a->l->data[i], buffer_fmt(tbuf, "qi_index(state, %s, qi_make_number(state, %d))", varname, i));
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "return %s;\n}\n", varname);
|
|
|
|
|
|
- case N_ASSIGN_ADD: COMPASSIGN(node->a, "add", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_SUB: COMPASSIGN(node->a, "sub", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_MUL: COMPASSIGN(node->a, "mul", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_DIV: COMPASSIGN(node->a, "div", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_IDIV: COMPASSIGN(node->a, "idiv", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_MOD: COMPASSIGN(node->a, "mod", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_POW: COMPASSIGN(node->a, "pow", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_BOR: COMPASSIGN(node->a, "bor", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
- case N_ASSIGN_BAND: COMPASSIGN(node->a, "band", compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b)); break;
|
|
|
|
|
|
+ buffer_appendb(gbuf, tbuf);
|
|
|
|
+
|
|
|
|
+ EMIT("__assign%d(state)", gid);
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ } else if (node->a->tag == N_TUPLE) {
|
|
|
|
+ if (node->a->l->length < 2)
|
|
|
|
+ COMPILE_ERROR("illegal multiple assignment left-hand side");
|
|
|
|
+
|
|
|
|
+ if (node->b->tag != N_TUPLE || node->b->l->length < 2 || node->a->l->length != node->b->l->length)
|
|
|
|
+ COMPILE_ERROR("illegal multiple assignment right-hand side");
|
|
|
|
+
|
|
|
|
+ NEWGID();
|
|
|
|
+
|
|
|
|
+ buffer_t *tbuf = buffer_new();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *__assign%d(qi_state_t *state) {\n", gid);
|
|
|
|
+
|
|
|
|
+ list_t *vals = list_new();
|
|
|
|
+ for (size_t i = 0; i < node->b->l->length; i++) {
|
|
|
|
+ char *varname = tempvar();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *%s = ", varname);
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->b->l->data[i]);
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+
|
|
|
|
+ list_push(vals, varname);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (size_t i = 0; i < node->a->l->length; i++) {
|
|
|
|
+ char *varname = vals->data[i];
|
|
|
|
+
|
|
|
|
+ ASSIGNIN(tbuf, (node_t *)node->a->l->data[i], buffer_fmt(tbuf, "%s", varname));
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "return %s;\n}\n", vals->data[vals->length-1]);
|
|
|
|
+
|
|
|
|
+ buffer_appendb(gbuf, tbuf);
|
|
|
|
+
|
|
|
|
+ EMIT("__assign%d(state)", gid);
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ASSIGN(node->a, compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case N_ASSIGN_ADD: COMPASSIGN(node->a, "add", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_SUB: COMPASSIGN(node->a, "sub", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_MUL: COMPASSIGN(node->a, "mul", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_DIV: COMPASSIGN(node->a, "div", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_IDIV: COMPASSIGN(node->a, "idiv", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_MOD: COMPASSIGN(node->a, "mod", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_POW: COMPASSIGN(node->a, "pow", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_BOR: COMPASSIGN(node->a, "bor", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
+ case N_ASSIGN_BAND: COMPASSIGN(node->a, "band", compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b)); break;
|
|
|
|
|
|
case N_INC:
|
|
case N_INC:
|
|
COMPASSIGN(node->a, "add", EMIT("state->one"));
|
|
COMPASSIGN(node->a, "add", EMIT("state->one"));
|
|
@@ -3354,48 +3459,57 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
EMIT("qi_%s(state, \"%s\", ", node->tag == N_LET? "decl_const": "decl", entry.key);
|
|
EMIT("qi_%s(state, \"%s\", ", node->tag == N_LET? "decl_const": "decl", entry.key);
|
|
|
|
|
|
if (entry.value)
|
|
if (entry.value)
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, entry.value);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, entry.value);
|
|
else EMIT("state->nil");
|
|
else EMIT("state->nil");
|
|
|
|
|
|
EMIT(");\n");
|
|
EMIT(");\n");
|
|
});
|
|
});
|
|
break;
|
|
break;
|
|
|
|
|
|
- case N_UNPACK: case N_VARUNPACK: case N_LETUNPACK: {
|
|
|
|
|
|
+ case N_VARUNPACK: case N_LETUNPACK: {
|
|
char *varname = tempvar();
|
|
char *varname = tempvar();
|
|
|
|
|
|
EMIT("qi_value_t *%s = ", varname);
|
|
EMIT("qi_value_t *%s = ", varname);
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(";\n");
|
|
EMIT(";\n");
|
|
|
|
|
|
for (size_t i = 0; i < node->l->length; i++)
|
|
for (size_t i = 0; i < node->l->length; i++)
|
|
- if (node->tag == N_UNPACK) {
|
|
|
|
- EMIT("qi_set(state, false, \"%s\", qi_index(state, %s, qi_make_number(state, %d)));\n", node->l->data[i], varname, i);
|
|
|
|
- } else {
|
|
|
|
- EMIT("%s(state, \"%s\", qi_index(state, %s, qi_make_number(state, %d)));\n", node->tag == N_VARUNPACK? "qi_decl": "qi_decl_const", node->l->data[i], varname, i);
|
|
|
|
- }
|
|
|
|
|
|
+ EMIT("%s(state, \"%s\", qi_index(state, %s, qi_make_number(state, %d)));\n", node->tag == N_VARUNPACK? "qi_decl": "qi_decl_const", node->l->data[i], varname, i);
|
|
} break;
|
|
} break;
|
|
|
|
|
|
case N_CONST:break;
|
|
case N_CONST:break;
|
|
|
|
|
|
case N_IF:
|
|
case N_IF:
|
|
EMIT("if (_qi_truthy(state, ");
|
|
EMIT("if (_qi_truthy(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(")) {\n");
|
|
EMIT(")) {\n");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
if (node->c) {
|
|
if (node->c) {
|
|
EMIT("} else {\n");
|
|
EMIT("} else {\n");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->c);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->c);
|
|
}
|
|
}
|
|
EMIT("}");
|
|
EMIT("}");
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_SWITCH: {
|
|
case N_SWITCH: {
|
|
NEWGID();
|
|
NEWGID();
|
|
|
|
+
|
|
|
|
+ if (node->t2) {
|
|
|
|
+ if (table_get(ltab, node->t2->text))
|
|
|
|
+ COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
|
|
+
|
|
|
|
+ stack_t *pair = stack_new();
|
|
|
|
+
|
|
|
|
+ stack_push(pair, 1);
|
|
|
|
+ stack_push(pair, gid);
|
|
|
|
+
|
|
|
|
+ table_set(ltab, node->t2->text, pair);
|
|
|
|
+ }
|
|
|
|
+
|
|
char *varname = tempvar();
|
|
char *varname = tempvar();
|
|
|
|
|
|
EMIT("qi_value_t *%s = ", varname);
|
|
EMIT("qi_value_t *%s = ", varname);
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(";\n");
|
|
EMIT(";\n");
|
|
|
|
|
|
for (size_t i = 0; i < node->l->length; i++) {
|
|
for (size_t i = 0; i < node->l->length; i++) {
|
|
@@ -3403,7 +3517,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
char *label = tempvar();
|
|
char *label = tempvar();
|
|
|
|
|
|
EMIT("if (_qi_equals(state, %s, ", varname);
|
|
EMIT("if (_qi_equals(state, %s, ", varname);
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, pair->data[0]);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, pair->data[0]);
|
|
EMIT(")) goto %s;\n", label);
|
|
EMIT(")) goto %s;\n", label);
|
|
|
|
|
|
pair->data[0] = label;
|
|
pair->data[0] = label;
|
|
@@ -3420,13 +3534,13 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
node_t *block = pair->data[1];
|
|
node_t *block = pair->data[1];
|
|
|
|
|
|
EMIT("%s:;\n", label);
|
|
EMIT("%s:;\n", label);
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, block);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, block);
|
|
}
|
|
}
|
|
|
|
|
|
EMIT("__default%d:;\n", gid);
|
|
EMIT("__default%d:;\n", gid);
|
|
|
|
|
|
if (node->b)
|
|
if (node->b)
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
CTXPOP();
|
|
CTXPOP();
|
|
SPOP();
|
|
SPOP();
|
|
@@ -3437,27 +3551,39 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
case N_FOR: {
|
|
case N_FOR: {
|
|
NEWGID();
|
|
NEWGID();
|
|
|
|
|
|
|
|
+ if (node->t2) {
|
|
|
|
+ if (table_get(ltab, node->t2->text))
|
|
|
|
+ COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
|
|
+
|
|
|
|
+ stack_t *pair = stack_new();
|
|
|
|
+
|
|
|
|
+ stack_push(pair, 0);
|
|
|
|
+ stack_push(pair, gid);
|
|
|
|
+
|
|
|
|
+ table_set(ltab, node->t2->text, pair);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (!node->a) {
|
|
if (!node->a) {
|
|
EMIT("for (;;) {\n");
|
|
EMIT("for (;;) {\n");
|
|
} else if (node->a && !node->b) {
|
|
} else if (node->a && !node->b) {
|
|
EMIT("while (_qi_truthy(state, ");
|
|
EMIT("while (_qi_truthy(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(")) {\n");
|
|
EMIT(")) {\n");
|
|
} else {
|
|
} else {
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT("while (_qi_truthy(state, ");
|
|
EMIT("while (_qi_truthy(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
EMIT(")) {\n");
|
|
EMIT(")) {\n");
|
|
}
|
|
}
|
|
|
|
|
|
LPUSH(gid);
|
|
LPUSH(gid);
|
|
CTXPUSH("for");
|
|
CTXPUSH("for");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->d);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->d);
|
|
|
|
|
|
EMIT("__continue%d:;\n", gid);
|
|
EMIT("__continue%d:;\n", gid);
|
|
|
|
|
|
if (node->c) {
|
|
if (node->c) {
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->c);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->c);
|
|
|
|
|
|
EMIT(";\n");
|
|
EMIT(";\n");
|
|
}
|
|
}
|
|
@@ -3472,10 +3598,23 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
case N_FOROF: case N_FOROFVAR: case N_FOROFUNPACK: case N_FOROFVARUNPACK: {
|
|
case N_FOROF: case N_FOROFVAR: case N_FOROFUNPACK: case N_FOROFVARUNPACK: {
|
|
NEWGID();
|
|
NEWGID();
|
|
|
|
+
|
|
|
|
+ if (node->t2) {
|
|
|
|
+ if (table_get(ltab, node->t2->text))
|
|
|
|
+ COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
|
|
+
|
|
|
|
+ stack_t *pair = stack_new();
|
|
|
|
+
|
|
|
|
+ stack_push(pair, 0);
|
|
|
|
+ stack_push(pair, gid);
|
|
|
|
+
|
|
|
|
+ table_set(ltab, node->t2->text, pair);
|
|
|
|
+ }
|
|
|
|
+
|
|
char *varname = tempvar();
|
|
char *varname = tempvar();
|
|
|
|
|
|
EMIT("qi_value_t *%s = qi_iter(state, ", varname);
|
|
EMIT("qi_value_t *%s = qi_iter(state, ", varname);
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(");\n");
|
|
EMIT(");\n");
|
|
|
|
|
|
if (node->tag == N_FOROFVAR) {
|
|
if (node->tag == N_FOROFVAR) {
|
|
@@ -3495,7 +3634,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
LPUSH(gid);
|
|
LPUSH(gid);
|
|
CTXPUSH("for");
|
|
CTXPUSH("for");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
CTXPOP();
|
|
CTXPOP();
|
|
LPOP();
|
|
LPOP();
|
|
|
|
|
|
@@ -3510,13 +3649,24 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
COMPILE_ERROR("break outside of a loop or a switch");
|
|
COMPILE_ERROR("break outside of a loop or a switch");
|
|
|
|
|
|
if (node->t) {
|
|
if (node->t) {
|
|
- unsigned int offset = abs(atoi(node->t->text)) + 1;
|
|
|
|
|
|
+ if (node->t->tag == T_NUMBER) {
|
|
|
|
+ unsigned int offset = abs(atoi(node->t->text)) + 1;
|
|
|
|
|
|
- if (offset < 2 || offset > lstk->length)
|
|
|
|
- COMPILE_ERROR("%d is not a valid break loop offset", offset-1);
|
|
|
|
|
|
+ if (offset < 2 || offset > lstk->length)
|
|
|
|
+ COMPILE_ERROR("%d is not a valid break loop offset", offset-1);
|
|
|
|
+
|
|
|
|
+ EMIT("goto __break%d;", lstk->data[lstk->length-offset]);
|
|
|
|
+ } else {
|
|
|
|
+ char *label = node->t->text;
|
|
|
|
|
|
- EMIT("goto __break%d;", lstk->data[lstk->length-offset]);
|
|
|
|
|
|
+ stack_t *pair = table_get(ltab, label);
|
|
|
|
|
|
|
|
+ if (!pair)
|
|
|
|
+ COMPILE_ERROR("undefined loop label: '%s'", label);
|
|
|
|
+
|
|
|
|
+ EMIT("goto __break%d;", pair->data[1]);
|
|
|
|
+ }
|
|
|
|
+
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3528,13 +3678,27 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
COMPILE_ERROR("continue outside of a loop");
|
|
COMPILE_ERROR("continue outside of a loop");
|
|
|
|
|
|
if (node->t) {
|
|
if (node->t) {
|
|
- unsigned int offset = abs(atoi(node->t->text)) + 1;
|
|
|
|
|
|
+ if (node->t->tag == T_NUMBER) {
|
|
|
|
+ unsigned int offset = abs(atoi(node->t->text)) + 1;
|
|
|
|
+
|
|
|
|
+ if (offset < 2 || offset > lstk->length)
|
|
|
|
+ COMPILE_ERROR("%d is not a valid break loop offset", offset-1);
|
|
|
|
+
|
|
|
|
+ EMIT("goto __continue%d;", lstk->data[lstk->length-offset]);
|
|
|
|
+ } else {
|
|
|
|
+ char *label = node->t->text;
|
|
|
|
+
|
|
|
|
+ stack_t *pair = table_get(ltab, label);
|
|
|
|
|
|
- if (offset < 2 || offset > lstk->length)
|
|
|
|
- COMPILE_ERROR("%d is not a valid continue loop offset", offset-1);
|
|
|
|
|
|
+ if (pair->data[1])
|
|
|
|
+ COMPILE_ERROR("continue on a switch loop label: '%s'", label);
|
|
|
|
|
|
- EMIT("goto __continue%d;", lstk->data[lstk->length-offset]);
|
|
|
|
|
|
+ if (!pair)
|
|
|
|
+ COMPILE_ERROR("undefined loop label: '%s'", label);
|
|
|
|
|
|
|
|
+ EMIT("goto __continue%d;", pair->data[1]);
|
|
|
|
+ }
|
|
|
|
+
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3550,7 +3714,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
LBPUSH();
|
|
LBPUSH();
|
|
CTXPUSH("gap");
|
|
CTXPUSH("gap");
|
|
- compile_node(gbuf, tbuf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
CTXPOP();
|
|
CTXPOP();
|
|
LBPOP();
|
|
LBPOP();
|
|
|
|
|
|
@@ -3575,7 +3739,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
EMIT("return ");
|
|
EMIT("return ");
|
|
|
|
|
|
if (node->a)
|
|
if (node->a)
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
else EMIT("state->nil");
|
|
else EMIT("state->nil");
|
|
|
|
|
|
EMIT(";");
|
|
EMIT(";");
|
|
@@ -3587,12 +3751,12 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
|
|
|
|
case N_TRY:
|
|
case N_TRY:
|
|
EMIT("qi_try(state, {\n");
|
|
EMIT("qi_try(state, {\n");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT("}, {\n");
|
|
EMIT("}, {\n");
|
|
if (node->t)
|
|
if (node->t)
|
|
EMIT("qi_decl(state, \"%s\", trap->value);\n", node->t->text);
|
|
EMIT("qi_decl(state, \"%s\", trap->value);\n", node->t->text);
|
|
CTXPUSH("trap");
|
|
CTXPUSH("trap");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
CTXPOP();
|
|
CTXPOP();
|
|
EMIT("}, NULL);\n");
|
|
EMIT("}, NULL);\n");
|
|
break;
|
|
break;
|
|
@@ -3600,7 +3764,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
case N_THROW:
|
|
case N_THROW:
|
|
EMIT("qi_throw(state, ");
|
|
EMIT("qi_throw(state, ");
|
|
if (node->a)
|
|
if (node->a)
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
else {
|
|
else {
|
|
EMIT("state->nil");
|
|
EMIT("state->nil");
|
|
}
|
|
}
|
|
@@ -3625,22 +3789,22 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
case N_REQUIRE: {
|
|
case N_REQUIRE: {
|
|
char *path = unescape(node->t->text);
|
|
char *path = unescape(node->t->text);
|
|
|
|
|
|
- if (require_once(gbuf, buf, ctx, lstk, sstk, lbl, path) < 0)
|
|
|
|
|
|
+ if (require_once(gbuf, buf, ctx, ltab, lstk, sstk, lbl, path) < 0)
|
|
COMPILE_ERROR("'%s' is not a valid file path or a builtin library name", path);
|
|
COMPILE_ERROR("'%s' is not a valid file path or a builtin library name", path);
|
|
} break;
|
|
} break;
|
|
|
|
|
|
case N_IFEXPR:
|
|
case N_IFEXPR:
|
|
EMIT("(_qi_truthy(state, ");
|
|
EMIT("(_qi_truthy(state, ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(")? ");
|
|
EMIT(")? ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
EMIT(": ");
|
|
EMIT(": ");
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, node->c);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->c);
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_FUNCEXPR:
|
|
case N_FUNCEXPR:
|
|
- compile_func(gbuf, buf, ctx, lstk, sstk, lbl, node, NULL);
|
|
|
|
|
|
+ compile_func(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, NULL);
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_EQUALS:
|
|
case N_EQUALS:
|
|
@@ -3759,25 +3923,25 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, sta
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, stack_t *sstk, list_t *lbl) {
|
|
|
|
|
|
+void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl) {
|
|
node_t *n = parse(source);
|
|
node_t *n = parse(source);
|
|
|
|
|
|
- compile_node(gbuf, buf, ctx, lstk, sstk, lbl, n);
|
|
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
|
|
}
|
|
}
|
|
|
|
|
|
char *compile(char *source) {
|
|
char *compile(char *source) {
|
|
list_t *ctx = list_new();
|
|
list_t *ctx = list_new();
|
|
|
|
+ table_t *ltab = table_new();
|
|
stack_t *lstk = stack_new();
|
|
stack_t *lstk = stack_new();
|
|
stack_t *sstk = stack_new();
|
|
stack_t *sstk = stack_new();
|
|
list_t *lbl = list_new();
|
|
list_t *lbl = list_new();
|
|
LBPUSH();
|
|
LBPUSH();
|
|
|
|
|
|
buffer_t *gbuf = buffer_new();
|
|
buffer_t *gbuf = buffer_new();
|
|
-
|
|
|
|
buffer_t *buf = buffer_new();
|
|
buffer_t *buf = buffer_new();
|
|
|
|
|
|
- require_once(gbuf, buf, ctx, lstk, sstk, lbl, "std");
|
|
|
|
- compile_into(source, gbuf, buf, ctx, lstk, sstk, lbl);
|
|
|
|
|
|
+ require_once(gbuf, buf, ctx, ltab, lstk, sstk, lbl, "std");
|
|
|
|
+ compile_into(source, gbuf, buf, ctx, ltab, lstk, sstk, lbl);
|
|
|
|
|
|
buffer_t *rbuf = buffer_new();
|
|
buffer_t *rbuf = buffer_new();
|
|
|
|
|