nuqneH 'u'?
This commit is contained in:
parent
881c6c7740
commit
14bf533635
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue