adding compilation of if-else statements

This commit is contained in:
cozis
2021-10-31 07:01:15 +00:00
parent 5e8fb7ef6b
commit 9eaa82297f
16 changed files with 269 additions and 25 deletions
+71 -2
View File
@@ -42,7 +42,8 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
OperExprNode *oper = (OperExprNode*) expr;
for(Node *operand = oper->head; operand; operand = operand->next)
emit_instr_for_node(exeb, operand, error);
if(!emit_instr_for_node(exeb, operand, error))
return 0;
return ExeBuilder_Append(exeb, error,
exprkind_to_opcode(expr->kind),
@@ -84,10 +85,78 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
break;
}
case NODE_IFELSE:
{
IfElseNode *ifelse = (IfElseNode*) node;
if(!emit_instr_for_node(exeb, ifelse->condition, error))
return 0;
if(ifelse->false_branch)
{
Promise *else_offset = Promise_New(ExeBuilder_GetAlloc(exeb), sizeof(long long int));
Promise *done_offset = Promise_New(ExeBuilder_GetAlloc(exeb), sizeof(long long int));
if(else_offset == NULL || done_offset == NULL)
{
Error_Report(error, 1, "No memory");
return 0;
}
Operand op = { .type = OPTP_PROMISE, .as_promise = else_offset };
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMPIFNOTANDPOP, &op, 1, node->offset, node->length))
return 0;
if(!emit_instr_for_node(exeb, ifelse->true_branch, error))
return 0;
op = (Operand) { .type = OPTP_PROMISE, .as_promise = done_offset };
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMP, &op, 1, node->offset, node->length))
return 0;
long long int temp = ExeBuilder_InstrCount(exeb);
Promise_Resolve(else_offset, &temp, sizeof(temp));
if(!emit_instr_for_node(exeb, ifelse->false_branch, error))
return 0;
temp = ExeBuilder_InstrCount(exeb);
Promise_Resolve(done_offset, &temp, sizeof(temp));
Promise_Free(else_offset);
Promise_Free(done_offset);
}
else
{
Promise *done_offset = Promise_New(ExeBuilder_GetAlloc(exeb), sizeof(long long int));
if(done_offset == NULL)
{
Error_Report(error, 1, "No memory");
return 0;
}
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMPIFNOTANDPOP, &(Operand) { .type = OPTP_PROMISE, .as_promise = done_offset }, 1, node->offset, node->length))
return 0;
if(!emit_instr_for_node(exeb, ifelse->true_branch, error))
return 0;
long long int temp = ExeBuilder_InstrCount(exeb);
Promise_Resolve(done_offset, &temp, sizeof(temp));
Promise_Free(done_offset);
}
return 1;
}
default:
UNREACHABLE;
break;
return 0;
}
UNREACHABLE;
return 0;
}
Executable *compile(AST *ast, BPAlloc *alloc, Error *error)
+30 -14
View File
@@ -369,7 +369,7 @@ static Node *parse_string_primary_expression(Context *ctx)
assert(ctx != NULL);
assert(ctx->token->kind == TSTRING);
if(current(ctx) == TDONE)
if(done(ctx))
{
Error_Report(ctx->error, 0, "Source ended where a string literal was expected");
return NULL;
@@ -493,6 +493,12 @@ static Node *parse_primary_expresion(Context *ctx)
{
assert(ctx != NULL);
if(done(ctx))
{
Error_Report(ctx->error, 0, "Source ended where a primary expression was expected");
return NULL;
}
switch(current(ctx))
{
case '+':
@@ -532,7 +538,7 @@ static Node *parse_primary_expresion(Context *ctx)
if(node == NULL)
return NULL;
if(current(ctx) == TDONE)
if(done(ctx))
{
Error_Report(ctx->error, 0, "Source ended before \")\", after sub-expression");
return NULL;
@@ -823,34 +829,44 @@ static Node *parse_ifelse_statement(Context *ctx)
{
assert(ctx != NULL);
assert(ctx->token != NULL);
assert(ctx->token->kind == TKWIF);
ctx->token = ctx->token->next;
if(ctx->token->kind == TDONE)
if(done(ctx))
{
// ERROR: Source ended after if keyword.
// An expression was expected.
Error_Report(ctx->error, 0, "Source ended after if keyword. An expression was expected");
Error_Report(ctx->error, 0, "Source ended where an if-else statement was expected");
return NULL;
}
if(current(ctx) != TKWIF)
{
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" where an if-else statement was expected", ctx->token->length, ctx->src + ctx->token->offset);
return NULL;
}
Token *if_token = current_token(ctx);
assert(if_token != NULL);
next(ctx); // Consume the "if" keyword.
Node *condition = parse_expression(ctx);
if(condition == NULL) return NULL;
if(condition == NULL)
return NULL;
Node *true_branch = parse_statement(ctx);
if(condition == NULL) return NULL;
if(condition == NULL)
return NULL;
Node *false_branch = NULL;
if(ctx->token->kind == TKWELSE)
{
// Consume the "else" token.
ctx->token = ctx->token->next;
next(ctx); // Consume the "else" token.
false_branch = parse_statement(ctx);
if(false_branch == NULL) return NULL;
if(false_branch == NULL)
return NULL;
}
IfElseNode *ifelse;
+21
View File
@@ -126,6 +126,27 @@ static xj_value *convert_node(Node *node, xj_error *error, xj_alloc **alloc)
}
break;
case NODE_IFELSE:
{
IfElseNode *ifelse = (IfElseNode*) node;
xj_value *condition = convert_node(ifelse->condition, error, alloc);
if(condition == NULL) return NULL;
xj_value *true_branch = convert_node(ifelse->true_branch, error, alloc);
if(true_branch == NULL) return NULL;
xj_value *false_branch = convert_node(ifelse->false_branch, error, alloc);
if(false_branch == NULL) return NULL;
return xj_decodef(error, alloc,
"{"
"\t\"node-kind\": \"if-else\", \n"
"\t\"condition\": %v, \n"
"\t\"true-branch\": %v, \n"
"\t\"false-branch\": %v\n"
"}", condition, true_branch, false_branch);
}
default:
UNREACHABLE;