while loops done

This commit is contained in:
2026-05-27 14:47:39 +10:00
parent 61d48ef453
commit cd131834e6
8 changed files with 209 additions and 12 deletions

View File

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

View File

@@ -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;

View File

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

View File

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

View File

@@ -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
}

View File

@@ -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;
}

View File

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

View File

@@ -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);
}