while loops done
This commit is contained in:
@@ -123,6 +123,31 @@ ResultType(CometOperand, charptr) visitAssignStatement(CometCompiler* c, CometAS
|
||||
|
||||
return Success(CometOperand, charptr, NO_OPERAND);
|
||||
}
|
||||
ResultType(CometOperand, charptr) visitReassignStatement(CometCompiler* c, CometASTNode* node) {
|
||||
ResultType(CometOperand, charptr) exprResult = resolveValue(c, node->data.AST_ASSIGN_STATEMENT.expression);
|
||||
if (exprResult.error)
|
||||
return exprResult;
|
||||
|
||||
char* ident = node->data.AST_ASSIGN_STATEMENT.ident->data.AST_IDENTIFIER.ident;
|
||||
|
||||
Record* varRecord = lookup(c->env, ident);
|
||||
if (!varRecord) {
|
||||
Estr errMsg = CREATE_ESTR("Cannot reassign undefined variable \"");
|
||||
APPEND_ESTR(errMsg, ident);
|
||||
APPEND_ESTR(errMsg, "\"");
|
||||
return Error(CometOperand, charptr, errMsg.str);
|
||||
}
|
||||
|
||||
if (!varRecord->isMutable) {
|
||||
Estr errMsg = CREATE_ESTR("Cannot change value of immutable variable \"");
|
||||
APPEND_ESTR(errMsg, ident);
|
||||
APPEND_ESTR(errMsg, "\", did you forget \"mut\"?");
|
||||
return Error(CometOperand, charptr, errMsg.str);
|
||||
}
|
||||
|
||||
buildStore(c, varRecord->recordIdx);
|
||||
return Success(CometOperand, charptr, NO_OPERAND);
|
||||
}
|
||||
|
||||
ResultType(CometOperand, charptr) visitInfixExpression(CometCompiler* c, CometASTNode* node) {
|
||||
struct AST_INFIX_EXPRESSION expr = node->data.AST_INFIX_EXPRESSION;
|
||||
@@ -155,6 +180,22 @@ ResultType(CometOperand, charptr) visitInfixExpression(CometCompiler* c, CometAS
|
||||
out = buildEq(c);
|
||||
break;
|
||||
}
|
||||
case CT_LT: {
|
||||
out = buildLt(c);
|
||||
break;
|
||||
}
|
||||
case CT_GT: {
|
||||
out = buildGt(c);
|
||||
break;
|
||||
}
|
||||
case CT_LTE: {
|
||||
out = buildLte(c);
|
||||
break;
|
||||
}
|
||||
case CT_GTE: {
|
||||
out = buildGte(c);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
Estr errMsg = CREATE_ESTR("Invalid operator \"");
|
||||
@@ -279,6 +320,36 @@ ResultType(CometOperand, charptr) visitIfStatement(CometCompiler* c, CometASTNod
|
||||
resolveLabel(c, endLabel);
|
||||
|
||||
|
||||
return Success(CometOperand, charptr, NO_OPERAND);
|
||||
}
|
||||
ResultType(CometOperand, charptr) visitWhileStatement(CometCompiler* c, CometASTNode* node) {
|
||||
struct AST_WHILE_STATEMENT whileStmt = node->data.AST_WHILE_STATEMENT;
|
||||
|
||||
CometLabel* startLabel = buildLabel(c);
|
||||
CometLabel* endLabel = buildLabel(c);
|
||||
|
||||
|
||||
|
||||
ResultType(CometOperand, charptr) condition = resolveValue(c, whileStmt.expression);
|
||||
if (condition.error)
|
||||
return condition;
|
||||
|
||||
buildJumpIfFalse(c, endLabel);
|
||||
resolveLabel(c, startLabel);
|
||||
|
||||
ResultType(CometOperand, charptr) whileBodyResult = compile(c, whileStmt.program);
|
||||
if (whileBodyResult.error)
|
||||
return whileBodyResult;
|
||||
|
||||
condition = resolveValue(c, whileStmt.expression);
|
||||
if (condition.error)
|
||||
return condition;
|
||||
|
||||
buildNot(c);
|
||||
buildJumpIfFalse(c, startLabel);
|
||||
|
||||
resolveLabel(c, endLabel);
|
||||
|
||||
return Success(CometOperand, charptr, NO_OPERAND);
|
||||
}
|
||||
|
||||
@@ -340,12 +411,16 @@ ResultType(CometOperand, charptr) compile(CometCompiler* c, CometASTNode* node)
|
||||
return visitExpressionStatement(c, node);
|
||||
case AST_ASSIGN_STATEMENT:
|
||||
return visitAssignStatement(c, node);
|
||||
case AST_REASSIGN_STATEMENT:
|
||||
return visitReassignStatement(c, node);
|
||||
case AST_FUNC_DEF_STATEMENT:
|
||||
return visitFuncDefStatement(c, node);
|
||||
case AST_RETURN_STATEMENT:
|
||||
return visitReturnStatement(c, node);
|
||||
case AST_IF_STATEMENT:
|
||||
return visitIfStatement(c, node);
|
||||
case AST_WHILE_STATEMENT:
|
||||
return visitWhileStatement(c, node);
|
||||
|
||||
case AST_FUNC_CALL:
|
||||
return visitFuncCall(c, node);
|
||||
|
||||
44
src/inst.c
44
src/inst.c
@@ -114,6 +114,10 @@ char* cometInstOpcodeToCStr(CometInstType instType) {
|
||||
case INST_RET : return " RET ";
|
||||
case INST_CALL : return " CALL ";
|
||||
case INST_EQ : return " EQ ";
|
||||
case INST_LT : return " LT ";
|
||||
case INST_GT : return " GT ";
|
||||
case INST_LTE : return " LTE ";
|
||||
case INST_GTE : return " GTE ";
|
||||
case INST_JMP : return " JMP ";
|
||||
case INST_JMP_IF_FALSE : return " JMP_IF_FALSE ";
|
||||
case INST_NOT : return " NOT ";
|
||||
@@ -382,6 +386,46 @@ CometOperand buildEq(CometCompiler* c) {
|
||||
|
||||
return dest;
|
||||
}
|
||||
CometOperand buildLt(CometCompiler* c) {
|
||||
popVal(c);
|
||||
popVal(c);
|
||||
|
||||
CometOperand dest = pushVal(c);
|
||||
|
||||
buildInst(c, INST_LT, NO_OPERAND, NO_OPERAND, NO_OPERAND);
|
||||
|
||||
return dest;
|
||||
}
|
||||
CometOperand buildGt(CometCompiler* c) {
|
||||
popVal(c);
|
||||
popVal(c);
|
||||
|
||||
CometOperand dest = pushVal(c);
|
||||
|
||||
buildInst(c, INST_GT, NO_OPERAND, NO_OPERAND, NO_OPERAND);
|
||||
|
||||
return dest;
|
||||
}
|
||||
CometOperand buildLte(CometCompiler* c) {
|
||||
popVal(c);
|
||||
popVal(c);
|
||||
|
||||
CometOperand dest = pushVal(c);
|
||||
|
||||
buildInst(c, INST_LTE, NO_OPERAND, NO_OPERAND, NO_OPERAND);
|
||||
|
||||
return dest;
|
||||
}
|
||||
CometOperand buildGte(CometCompiler* c) {
|
||||
popVal(c);
|
||||
popVal(c);
|
||||
|
||||
CometOperand dest = pushVal(c);
|
||||
|
||||
buildInst(c, INST_GTE, NO_OPERAND, NO_OPERAND, NO_OPERAND);
|
||||
|
||||
return dest;
|
||||
}
|
||||
CometOperand buildFunction(CometCompiler* c, char* name, uint32_t argCount) {
|
||||
CometFunction* newFunction = malloc(sizeof(CometFunction));
|
||||
newFunction->argCount = argCount;
|
||||
|
||||
@@ -21,6 +21,10 @@ typedef enum {
|
||||
INST_RET,
|
||||
INST_CALL,
|
||||
INST_EQ,
|
||||
INST_GT,
|
||||
INST_LT,
|
||||
INST_GTE,
|
||||
INST_LTE,
|
||||
INST_JMP,
|
||||
INST_JMP_IF_FALSE,
|
||||
INST_NOT
|
||||
@@ -86,6 +90,10 @@ CometOperand buildAdd(CometCompiler* c);
|
||||
CometOperand buildSub(CometCompiler* c);
|
||||
CometOperand buildMul(CometCompiler* c);
|
||||
CometOperand buildEq(CometCompiler* c);
|
||||
CometOperand buildLt(CometCompiler* c);
|
||||
CometOperand buildGt(CometCompiler* c);
|
||||
CometOperand buildLte(CometCompiler* c);
|
||||
CometOperand buildGte(CometCompiler* c);
|
||||
CometOperand buildFunction(CometCompiler* c, char* name, uint32_t argCount);
|
||||
void buildReturn(CometCompiler* c);
|
||||
CometOperand buildLoadArg(CometCompiler* c, uint32_t idx);
|
||||
|
||||
@@ -62,10 +62,6 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < compiler.as.success->programIdx; i++) {
|
||||
printf("%s\n", cometInstructionToCStr(compiler.as.success, compiler.as.success->outputProgram[i]));
|
||||
}
|
||||
|
||||
ResultType(voidPtr, charptr) writeSuccess = outputToFile(compiler.as.success, args.as.success.outputPath);
|
||||
if (writeSuccess.error) {
|
||||
fprintf(stderr, "error while writing output: %s\n", writeSuccess.as.error);
|
||||
|
||||
26
test.comet
26
test.comet
@@ -1,7 +1,27 @@
|
||||
func main() -> int {
|
||||
if 6 * 6 == 36 {
|
||||
func fib(int n) -> int {
|
||||
if n <= 0 {
|
||||
return 0
|
||||
}
|
||||
if n == 1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 1
|
||||
mut int a = 0
|
||||
mut int b = 1
|
||||
mut int i = 2
|
||||
mut int temp = 0
|
||||
|
||||
while i <= n {
|
||||
temp = a + b
|
||||
a = b
|
||||
b = temp
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func main() -> int {
|
||||
int result = fib(92)
|
||||
return result
|
||||
}
|
||||
@@ -2,10 +2,13 @@
|
||||
#include "args.h"
|
||||
#include "../lib/ansi.h"
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define VERSION_NUMBER "0.1.0"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
|
||||
// parse command line args
|
||||
ResultType(CometArgs, charptr) args = parseArgs(argc, argv);
|
||||
if (args.error) {
|
||||
@@ -26,11 +29,20 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
clock_t start = clock();
|
||||
ResultType(int, charptr) result = startVM(newVm.as.success);
|
||||
clock_t end = clock();
|
||||
|
||||
|
||||
if (result.error) {
|
||||
fprintf(stderr, "error while executing: %s\n", result.as.error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||
printf("Execution took %f seconds\n", time_spent);
|
||||
|
||||
return result.as.success;
|
||||
}
|
||||
@@ -14,6 +14,10 @@ typedef enum {
|
||||
INST_RET,
|
||||
INST_CALL,
|
||||
INST_EQ,
|
||||
INST_GT,
|
||||
INST_LT,
|
||||
INST_GTE,
|
||||
INST_LTE,
|
||||
INST_JMP,
|
||||
INST_JMP_IF_FALSE,
|
||||
INST_NOT
|
||||
|
||||
48
vm_src/vm.c
48
vm_src/vm.c
@@ -140,7 +140,7 @@ void returnFromFunc(CometVM* vm) {
|
||||
free(funcFrame);
|
||||
}
|
||||
|
||||
ResultType(voidPtr, charptr) clock(CometVM* vm) {
|
||||
ResultType(voidPtr, charptr) vmClock(CometVM* vm) {
|
||||
CometSerializedInst inst = vm->instructions[vm->currentFrame->ip];
|
||||
vm->currentFrame->ip++;
|
||||
|
||||
@@ -183,12 +183,41 @@ ResultType(voidPtr, charptr) clock(CometVM* vm) {
|
||||
push(vm, a == b);
|
||||
break;
|
||||
}
|
||||
case INST_LT: {
|
||||
int64_t b = pop(vm);
|
||||
int64_t a = pop(vm);
|
||||
|
||||
printf("a: %d, b: %d\n", a, b);
|
||||
|
||||
push(vm, a < b);
|
||||
break;
|
||||
}
|
||||
case INST_GT: {
|
||||
int64_t b = pop(vm);
|
||||
int64_t a = pop(vm);
|
||||
|
||||
push(vm, a > b);
|
||||
break;
|
||||
}
|
||||
case INST_LTE: {
|
||||
int64_t b = pop(vm);
|
||||
int64_t a = pop(vm);
|
||||
|
||||
push(vm, a <= b);
|
||||
break;
|
||||
}
|
||||
case INST_GTE: {
|
||||
int64_t b = pop(vm);
|
||||
int64_t a = pop(vm);
|
||||
|
||||
push(vm, a >= b);
|
||||
break;
|
||||
}
|
||||
|
||||
case INST_JMP_IF_FALSE: {
|
||||
int64_t a = pop(vm);
|
||||
|
||||
if (!a) {
|
||||
printf("%d\n", inst.a);
|
||||
vm->currentFrame->ip = inst.a;
|
||||
}
|
||||
break;
|
||||
@@ -224,8 +253,17 @@ ResultType(voidPtr, charptr) clock(CometVM* vm) {
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return Error(voidPtr, charptr, "Reached invalid instruction!");
|
||||
case INST_NOT: {
|
||||
int64_t value = pop(vm);
|
||||
push(vm, !value);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
char* buffer = malloc(128);
|
||||
sprintf(buffer, "Reached invalid instruction! (%d)", inst.opcode);
|
||||
return Error(voidPtr, charptr, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +278,7 @@ ResultType(int, charptr) startVM(CometVM* vm) {
|
||||
callFunction(vm, mainFunc);
|
||||
|
||||
while (vm->running) {
|
||||
ResultType(voidPtr, charptr) instResult = clock(vm);
|
||||
ResultType(voidPtr, charptr) instResult = vmClock(vm);
|
||||
if (instResult.error)
|
||||
return Error(int, charptr, instResult.as.error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user