added compound statements

This commit is contained in:
cozis
2021-11-01 03:20:07 +00:00
parent e67231f321
commit 97c3c15ea0
8 changed files with 138 additions and 4 deletions
+1
View File
@@ -1,2 +1,3 @@
build build
temp temp
vgcore.*
+8 -1
View File
@@ -1,2 +1,9 @@
if true 3; else none; if false
{
3;
2;
}
else
4;
99;
+2
View File
@@ -48,6 +48,8 @@ static const InstrInfo instr_table[] = {
[OPCODE_MUL] = {"MUL", 0, NULL}, [OPCODE_MUL] = {"MUL", 0, NULL},
[OPCODE_DIV] = {"DIV", 0, NULL}, [OPCODE_DIV] = {"DIV", 0, NULL},
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}}, [OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}}, [OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}},
[OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}}, [OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}},
+1
View File
@@ -28,6 +28,7 @@ typedef enum {
OPCODE_SUB, OPCODE_SUB,
OPCODE_MUL, OPCODE_MUL,
OPCODE_DIV, OPCODE_DIV,
OPCODE_POP,
OPCODE_PUSHINT, OPCODE_PUSHINT,
OPCODE_PUSHFLT, OPCODE_PUSHFLT,
OPCODE_PUSHSTR, OPCODE_PUSHSTR,
+5
View File
@@ -7,6 +7,7 @@
typedef enum { typedef enum {
NODE_EXPR, NODE_EXPR,
NODE_IFELSE, NODE_IFELSE,
NODE_COMP,
} NodeKind; } NodeKind;
typedef enum { typedef enum {
@@ -81,4 +82,8 @@ typedef struct {
Node *false_branch; Node *false_branch;
} IfElseNode; } IfElseNode;
typedef struct {
Node base;
Node *head;
} CompoundNode;
#endif #endif
+45
View File
@@ -119,6 +119,13 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
if(!emit_instr_for_node(exeb, ifelse->true_branch, error)) if(!emit_instr_for_node(exeb, ifelse->true_branch, error))
return 0; return 0;
if(ifelse->true_branch->kind == NODE_EXPR)
{
Operand op = (Operand) { .type = OPTP_INT, .as_int = 1 };
if(!ExeBuilder_Append(exeb, error, OPCODE_POP, &op, 1, ifelse->true_branch->offset, 0))
return 0;
}
op = (Operand) { .type = OPTP_PROMISE, .as_promise = done_offset }; op = (Operand) { .type = OPTP_PROMISE, .as_promise = done_offset };
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMP, &op, 1, node->offset, node->length)) if(!ExeBuilder_Append(exeb, error, OPCODE_JUMP, &op, 1, node->offset, node->length))
return 0; return 0;
@@ -129,6 +136,13 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
if(!emit_instr_for_node(exeb, ifelse->false_branch, error)) if(!emit_instr_for_node(exeb, ifelse->false_branch, error))
return 0; return 0;
if(ifelse->false_branch->kind == NODE_EXPR)
{
Operand op = (Operand) { .type = OPTP_INT, .as_int = 1 };
if(!ExeBuilder_Append(exeb, error, OPCODE_POP, &op, 1, ifelse->false_branch->offset, 0))
return 0;
}
temp = ExeBuilder_InstrCount(exeb); temp = ExeBuilder_InstrCount(exeb);
Promise_Resolve(done_offset, &temp, sizeof(temp)); Promise_Resolve(done_offset, &temp, sizeof(temp));
@@ -151,6 +165,13 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
if(!emit_instr_for_node(exeb, ifelse->true_branch, error)) if(!emit_instr_for_node(exeb, ifelse->true_branch, error))
return 0; return 0;
if(ifelse->true_branch->kind == NODE_EXPR)
{
Operand op = (Operand) { .type = OPTP_INT, .as_int = 1 };
if(!ExeBuilder_Append(exeb, error, OPCODE_POP, &op, 1, ifelse->true_branch->offset, 0))
return 0;
}
long long int temp = ExeBuilder_InstrCount(exeb); long long int temp = ExeBuilder_InstrCount(exeb);
Promise_Resolve(done_offset, &temp, sizeof(temp)); Promise_Resolve(done_offset, &temp, sizeof(temp));
@@ -160,6 +181,30 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
return 1; return 1;
} }
case NODE_COMP:
{
CompoundNode *comp = (CompoundNode*) node;
Node *stmt = comp->head;
while(stmt)
{
if(!emit_instr_for_node(exeb, stmt, error))
return 0;
if(stmt->kind == NODE_EXPR)
{
Operand op = (Operand) { .type = OPTP_INT, .as_int = 1 };
if(!ExeBuilder_Append(exeb, error, OPCODE_POP, &op, 1, stmt->offset, 0))
return 0;
}
stmt = stmt->next;
}
return 1;
}
default: default:
UNREACHABLE; UNREACHABLE;
return 0; return 0;
+64 -2
View File
@@ -49,6 +49,7 @@ static Node *parse_statement(Context *ctx);
static Node *parse_expression(Context *ctx); static Node *parse_expression(Context *ctx);
static Node *parse_expression_statement(Context *ctx); static Node *parse_expression_statement(Context *ctx);
static Node *parse_ifelse_statement(Context *ctx); static Node *parse_ifelse_statement(Context *ctx);
static Node *parse_compound_statement(Context *ctx, TokenKind end);
static inline _Bool isoper(char c) static inline _Bool isoper(char c)
{ {
@@ -275,7 +276,7 @@ AST *parse(Source *src, BPAlloc *alloc, Error *error)
ctx.alloc = alloc; ctx.alloc = alloc;
ctx.error = error; ctx.error = error;
Node *root = parse_statement(&ctx); Node *root = parse_compound_statement(&ctx, TDONE);
if(root == NULL) if(root == NULL)
return NULL; return NULL;
@@ -352,6 +353,19 @@ static Node *parse_statement(Context *ctx)
case TKWIF: case TKWIF:
return parse_ifelse_statement(ctx); return parse_ifelse_statement(ctx);
case '{':
{
next(ctx); // Consume the '{'.
Node *node = parse_compound_statement(ctx, '}');
if(node != NULL)
next(ctx); // Consume the '}'.
return node;
}
} }
Error_Report(ctx->error, 0, "Got token \"%.*s\" where the start of a statement was expected", Error_Report(ctx->error, 0, "Got token \"%.*s\" where the start of a statement was expected",
@@ -834,7 +848,7 @@ static inline int precedenceof(Token *tok)
return 2; return 2;
default: default:
return -10000000; return -100000000;
} }
UNREACHABLE; UNREACHABLE;
@@ -981,3 +995,51 @@ static Node *parse_ifelse_statement(Context *ctx)
return (Node*) ifelse; return (Node*) ifelse;
} }
static Node *parse_compound_statement(Context *ctx, TokenKind end)
{
int end_offset;
Node *head, **tail;
tail = &head;
*tail = NULL;
while(current(ctx) != end && current(ctx) != TDONE)
{
Node *temp = parse_statement(ctx);
if(temp == NULL)
return NULL;
*tail = temp;
tail = &temp->next;
end_offset = temp->offset + temp->length;
}
if(current(ctx) != end)
{
Error_Report(ctx->error, 0, "Source ended inside compound statement");
return NULL;
}
CompoundNode *node;
{
node = BPAlloc_Malloc(ctx->alloc, sizeof(CompoundNode));
if(node == NULL)
{
// ERROR: No memory.
Error_Report(ctx->error, 1, "No memory");
return NULL;
}
node->base.kind = NODE_COMP;
node->base.next = NULL;
node->base.offset = head->offset;
node->base.length = end_offset - head->offset;
node->head = head;
}
return (Node*) node;
}
+11
View File
@@ -342,6 +342,8 @@ static _Bool step(Runtime *runtime, Error *error)
case OPCODE_MUL: case OPCODE_MUL:
case OPCODE_DIV: case OPCODE_DIV:
{ {
assert(opc == 0);
Object *rop = Stack_Top(runtime->stack, 0); Object *rop = Stack_Top(runtime->stack, 0);
Object *lop = Stack_Top(runtime->stack, -1); Object *lop = Stack_Top(runtime->stack, -1);
@@ -363,6 +365,15 @@ static _Bool step(Runtime *runtime, Error *error)
break; break;
} }
case OPCODE_POP:
{
assert(opc == 1);
if(!Runtime_Pop(runtime, error, ops[0].as_int))
return 0;
return 1;
}
case OPCODE_PUSHINT: case OPCODE_PUSHINT:
{ {
assert(opc == 1); assert(opc == 1);