diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index 26dd857..a064cef 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -41,11 +41,12 @@ static void repl(VM *vm) { vm->cp = 0; vm->sp = 0; vm->pc = 0; + vm->mp = 0; compile(line, vm); - core_dump(vm); while (step_vm(vm)); } + exit(0); } int main(int argc, char **argv) { diff --git a/src/compiler.c b/src/compiler.c index 9db8655..4d65e03 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -1,4 +1,5 @@ #include "compiler.h" +#include typedef struct { Token current; @@ -75,12 +76,26 @@ void consume(TokenType type, const char *message) { errorAtCurrent(message); } + +static bool check(TokenType type) { + return parser.current.type == type; +} + +static bool match(TokenType type) { + if (!check(type)) return false; + advance(); + return true; +} + + void emitOp(VM *vm, uint8_t opcode, uint8_t dest, uint8_t src1, uint8_t src2) { vm->code[vm->cp++].u = OP(opcode, dest, src1, src2); } void expression(VM *vm); +void statement(VM *vm); +void declaration(VM *vm); ParseRule *getRule(TokenType type); void parsePrecedence(VM *vm, Precedence precedence); @@ -105,6 +120,23 @@ void number(VM *vm) { errorAtCurrent("Invalid number format"); } +void string(VM *vm) { + uint32_t length = parser.previous.length - 2; + uint32_t str_addr = vm->mp; + vm->memory[vm->mp++].u = length; + uint32_t i, j = 0; + for (i = 0; i < length; i++) { + vm->memory[vm->mp].c[i % 4] = parser.previous.start[i + 1]; + if (++j == 4) { + j = 0; + vm->mp++; + } + } + vm->frames[vm->fp].allocated.end += length / 4; + emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0); + vm->code[vm->cp++].u = str_addr; +} + void grouping(VM *vm) { expression(vm); consume(TOKEN_RPAREN, "Expect ')' after expression."); @@ -121,6 +153,27 @@ void unary(VM *vm) { } } +static void literal(VM *vm) { + switch (parser.previous.type) { + case TOKEN_KEYWORD_NIL: { + emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0); + vm->code[vm->cp++].u = 0; + break; + } + case TOKEN_KEYWORD_FALSE: { + emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0); + vm->code[vm->cp++].u = 0; + break; + } + case TOKEN_KEYWORD_TRUE: { + emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0); + vm->code[vm->cp++].u = 1; + break; + } + default: return; + } +} + void binary(VM *vm) { TokenType operatorType = parser.previous.type; ParseRule *rule = getRule(operatorType); @@ -246,7 +299,7 @@ ParseRule rules[] = { [TOKEN_LT] = {NULL, NULL, PREC_NONE}, [TOKEN_LTE] = {NULL, NULL, PREC_NONE}, [TOKEN_IDENTIFIER] = {NULL, NULL, PREC_NONE}, - [TOKEN_STRING_LITERAL] = {NULL, NULL, PREC_NONE}, + [TOKEN_STRING_LITERAL] = {string, NULL, PREC_NONE}, [TOKEN_INT_LITERAL] = {number, NULL, PREC_NONE}, [TOKEN_UINT_LITERAL] = {number, NULL, PREC_NONE}, [TOKEN_FLOAT_LITERAL] = {number, NULL, PREC_NONE}, @@ -257,9 +310,9 @@ ParseRule rules[] = { [TOKEN_OPERATOR_AND] = {NULL, binary, PREC_NONE}, [TOKEN_OPERATOR_OR] = {NULL, binary, PREC_NONE}, [TOKEN_OPERATOR_NOT] = {unary, NULL, PREC_NONE}, - [TOKEN_KEYWORD_NIL] = {NULL, NULL, PREC_NONE}, - [TOKEN_KEYWORD_TRUE] = {NULL, NULL, PREC_NONE}, - [TOKEN_KEYWORD_FALSE] = {NULL, NULL, PREC_NONE}, + [TOKEN_KEYWORD_NIL] = {literal, NULL, PREC_NONE}, + [TOKEN_KEYWORD_TRUE] = {literal, NULL, PREC_NONE}, + [TOKEN_KEYWORD_FALSE] = {literal, NULL, PREC_NONE}, [TOKEN_KEYWORD_PRINT] = {NULL, NULL, PREC_NONE}, [TOKEN_KEYWORD_RETURN] = {NULL, NULL, PREC_NONE}, [TOKEN_KEYWORD_THIS] = {NULL, NULL, PREC_NONE}, @@ -290,6 +343,31 @@ void parsePrecedence(VM *vm, Precedence precedence) { void expression(VM *vm) { parsePrecedence(vm, PREC_ASSIGNMENT); } +void printStatement(VM *vm) { + expression(vm); + consume(TOKEN_SEMICOLON, "Expect ';' after value."); + Frame f = vm->frames[vm->fp]; + vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, f.rp--, 0); +} + +static void expressionStatement(VM *vm) { + expression(vm); + consume(TOKEN_SEMICOLON, "Expect ';' after expression."); +} + +void statement(VM *vm) { + if (match(TOKEN_KEYWORD_PRINT)) { + printStatement(vm); + } else { + expressionStatement(vm); + } +} + +void declaration(VM *vm) { + statement(vm); +} + + bool compile(const char *source, VM *vm) { initLexer(source); @@ -297,8 +375,11 @@ bool compile(const char *source, VM *vm) { parser.panicMode = false; advance(); - expression(vm); - consume(TOKEN_EOF, "end of file"); + + while (!match(TOKEN_EOF)) { + declaration(vm); + } + emitOp(vm, OP_HALT, 0, 0, 0); return !parser.hadError;