added compound statements
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
build
|
build
|
||||||
temp
|
temp
|
||||||
|
vgcore.*
|
||||||
@@ -1,2 +1,9 @@
|
|||||||
|
|
||||||
if true 3; else none;
|
if false
|
||||||
|
{
|
||||||
|
3;
|
||||||
|
2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
4;
|
||||||
|
99;
|
||||||
@@ -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}},
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user