diff --git a/samples/if-else.noja b/samples/if-else.noja index bc5f155..797966b 100644 --- a/samples/if-else.noja +++ b/samples/if-else.noja @@ -1,9 +1,9 @@ -if false - { - 3; +if true + { + return 3; 2; - } + } else 4; -99; \ No newline at end of file +return 99; \ No newline at end of file diff --git a/src/compiler/ASTi.h b/src/compiler/ASTi.h index 7c81a72..4a9c049 100644 --- a/src/compiler/ASTi.h +++ b/src/compiler/ASTi.h @@ -8,6 +8,7 @@ typedef enum { NODE_EXPR, NODE_IFELSE, NODE_COMP, + NODE_RETURN, } NodeKind; typedef enum { @@ -86,4 +87,9 @@ typedef struct { Node base; Node *head; } CompoundNode; + +typedef struct { + Node base; + Node *val; +} ReturnNode; #endif \ No newline at end of file diff --git a/src/compiler/compile.c b/src/compiler/compile.c index 9e7b5e9..e132cdb 100644 --- a/src/compiler/compile.c +++ b/src/compiler/compile.c @@ -205,6 +205,19 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error) return 1; } + case NODE_RETURN: + { + ReturnNode *ret = (ReturnNode*) node; + + if(!emit_instr_for_node(exeb, ret->val, error)) + return 0; + + if(!ExeBuilder_Append(exeb, error, OPCODE_RETURN, NULL, 0, ret->base.offset, ret->base.length)) + return 0; + + return 1; + } + default: UNREACHABLE; return 0; diff --git a/src/compiler/parse.c b/src/compiler/parse.c index 976ee58..b3827cb 100644 --- a/src/compiler/parse.c +++ b/src/compiler/parse.c @@ -29,6 +29,7 @@ typedef enum { TKWNONE, TKWTRUE, TKWFALSE, + TKWRETURN, } TokenKind; typedef struct Token Token; @@ -140,6 +141,10 @@ AST *parse(Source *src, BPAlloc *alloc, Error *error) { tok->kind = TKWFALSE; } + else if(matchstr(str + tok->offset, tok->length, "return")) + { + tok->kind = TKWRETURN; + } #undef matchstr } @@ -366,6 +371,32 @@ static Node *parse_statement(Context *ctx) return node; } + case TKWRETURN: + { + int offset = current_token(ctx)->offset; + + next(ctx); // Consume the "return" keyword. + + Node *val = parse_expression_statement(ctx); + + if(val == NULL) + return NULL; + + ReturnNode *node = BPAlloc_Malloc(ctx->alloc, sizeof(ReturnNode)); + + if(node == NULL) + { + Error_Report(ctx->error, 1, "No memory"); + return NULL; + } + + node->base.kind = NODE_RETURN; + node->base.next = NULL; + node->base.offset = offset; + node->base.length = val->offset + val->length - offset; + node->val = val; + return (Node*) node; + } } Error_Report(ctx->error, 0, "Got token \"%.*s\" where the start of a statement was expected", diff --git a/src/main.c b/src/main.c index bc4ebb0..eaaab31 100644 --- a/src/main.c +++ b/src/main.c @@ -328,7 +328,60 @@ int main(int argc, char **argv) case DISASSEMBLY: { + // Load + Source *src; + { + if(opts.input_is_file) + src = Source_FromFile(opts.input, &error); + else + src = Source_FromString(NULL, opts.input, -1, &error); + + if(src == NULL) + { + fprintf(stderr, "FATAL: %s.\n", error.message); + return 1; + } + } + + // Compile + Executable *exe; + { + BPAlloc *alloc = BPAlloc_Init(-1); + + if(alloc == NULL) + return 1; + + AST *ast = parse(src, alloc, &error); + + if(ast == NULL) + { + fprintf(stderr, "PARSING ERROR: %s.\n", error.message); + + Error_Free(&error); + BPAlloc_Free(alloc); + Source_Free(src); + return 1; + } + + exe = compile(ast, alloc, &error); + + if(exe == NULL) + { + fprintf(stderr, "COMPILATION ERROR: %s.\n", error.message); + + Error_Free(&error); + BPAlloc_Free(alloc); + Source_Free(src); + return 1; + } + + BPAlloc_Free(alloc); + } + Executable_Dump(exe); + + Executable_Free(exe); + Source_Free(src); return 1; }