nuqneH 'u'?

This commit is contained in:
zongor 2025-08-03 17:46:39 -04:00
parent 881c6c7740
commit 14bf533635
2 changed files with 89 additions and 7 deletions

View File

@ -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) {

View File

@ -1,4 +1,5 @@
#include "compiler.h"
#include <stdio.h>
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;