nuqneH 'u'?
This commit is contained in:
parent
881c6c7740
commit
14bf533635
|
@ -41,11 +41,12 @@ static void repl(VM *vm) {
|
||||||
vm->cp = 0;
|
vm->cp = 0;
|
||||||
vm->sp = 0;
|
vm->sp = 0;
|
||||||
vm->pc = 0;
|
vm->pc = 0;
|
||||||
|
vm->mp = 0;
|
||||||
|
|
||||||
compile(line, vm);
|
compile(line, vm);
|
||||||
core_dump(vm);
|
|
||||||
while (step_vm(vm));
|
while (step_vm(vm));
|
||||||
}
|
}
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Token current;
|
Token current;
|
||||||
|
@ -75,12 +76,26 @@ void consume(TokenType type, const char *message) {
|
||||||
errorAtCurrent(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,
|
void emitOp(VM *vm, uint8_t opcode, uint8_t dest, uint8_t src1,
|
||||||
uint8_t src2) {
|
uint8_t src2) {
|
||||||
vm->code[vm->cp++].u = OP(opcode, dest, src1, src2);
|
vm->code[vm->cp++].u = OP(opcode, dest, src1, src2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expression(VM *vm);
|
void expression(VM *vm);
|
||||||
|
void statement(VM *vm);
|
||||||
|
void declaration(VM *vm);
|
||||||
ParseRule *getRule(TokenType type);
|
ParseRule *getRule(TokenType type);
|
||||||
void parsePrecedence(VM *vm, Precedence precedence);
|
void parsePrecedence(VM *vm, Precedence precedence);
|
||||||
|
|
||||||
|
@ -105,6 +120,23 @@ void number(VM *vm) {
|
||||||
errorAtCurrent("Invalid number format");
|
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) {
|
void grouping(VM *vm) {
|
||||||
expression(vm);
|
expression(vm);
|
||||||
consume(TOKEN_RPAREN, "Expect ')' after expression.");
|
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) {
|
void binary(VM *vm) {
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser.previous.type;
|
||||||
ParseRule *rule = getRule(operatorType);
|
ParseRule *rule = getRule(operatorType);
|
||||||
|
@ -246,7 +299,7 @@ ParseRule rules[] = {
|
||||||
[TOKEN_LT] = {NULL, NULL, PREC_NONE},
|
[TOKEN_LT] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_LTE] = {NULL, NULL, PREC_NONE},
|
[TOKEN_LTE] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_IDENTIFIER] = {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_INT_LITERAL] = {number, NULL, PREC_NONE},
|
||||||
[TOKEN_UINT_LITERAL] = {number, NULL, PREC_NONE},
|
[TOKEN_UINT_LITERAL] = {number, NULL, PREC_NONE},
|
||||||
[TOKEN_FLOAT_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_AND] = {NULL, binary, PREC_NONE},
|
||||||
[TOKEN_OPERATOR_OR] = {NULL, binary, PREC_NONE},
|
[TOKEN_OPERATOR_OR] = {NULL, binary, PREC_NONE},
|
||||||
[TOKEN_OPERATOR_NOT] = {unary, NULL, PREC_NONE},
|
[TOKEN_OPERATOR_NOT] = {unary, NULL, PREC_NONE},
|
||||||
[TOKEN_KEYWORD_NIL] = {NULL, NULL, PREC_NONE},
|
[TOKEN_KEYWORD_NIL] = {literal, NULL, PREC_NONE},
|
||||||
[TOKEN_KEYWORD_TRUE] = {NULL, NULL, PREC_NONE},
|
[TOKEN_KEYWORD_TRUE] = {literal, NULL, PREC_NONE},
|
||||||
[TOKEN_KEYWORD_FALSE] = {NULL, NULL, PREC_NONE},
|
[TOKEN_KEYWORD_FALSE] = {literal, NULL, PREC_NONE},
|
||||||
[TOKEN_KEYWORD_PRINT] = {NULL, NULL, PREC_NONE},
|
[TOKEN_KEYWORD_PRINT] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_KEYWORD_RETURN] = {NULL, NULL, PREC_NONE},
|
[TOKEN_KEYWORD_RETURN] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_KEYWORD_THIS] = {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 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) {
|
bool compile(const char *source, VM *vm) {
|
||||||
initLexer(source);
|
initLexer(source);
|
||||||
|
|
||||||
|
@ -297,8 +375,11 @@ bool compile(const char *source, VM *vm) {
|
||||||
parser.panicMode = false;
|
parser.panicMode = false;
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
expression(vm);
|
|
||||||
consume(TOKEN_EOF, "end of file");
|
while (!match(TOKEN_EOF)) {
|
||||||
|
declaration(vm);
|
||||||
|
}
|
||||||
|
|
||||||
emitOp(vm, OP_HALT, 0, 0, 0);
|
emitOp(vm, OP_HALT, 0, 0, 0);
|
||||||
|
|
||||||
return !parser.hadError;
|
return !parser.hadError;
|
||||||
|
|
Loading…
Reference in New Issue