Math stuff (with order of operations yay)

This commit is contained in:
2026-02-26 18:06:41 +11:00
parent f5068fe861
commit 5cec2c1852
4 changed files with 328 additions and 2 deletions

View File

@@ -64,6 +64,39 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
}
return Error(SolsType, charptr, "Cannot add these types together");
}
case SNT_OP_MUL:
case SNT_OP_DIV:
case SNT_OP_SUB: {
if (node->children.count < 2) {
return Error(SolsType, charptr, "Not enough children to determine type");
}
ResultType(SolsType, charptr) leftType = getNodeType(&node->children.at[0], scope);
if (leftType.error) {
return Error(SolsType, charptr, leftType.as.error);
}
ResultType(SolsType, charptr) rightType = getNodeType(&node->children.at[1], scope);
if (rightType.error) {
return Error(SolsType, charptr, rightType.as.error);
}
if (!(leftType.as.success.type == STT_INT || leftType.as.success.type == STT_DOUBLE)) {
return Error(SolsType, charptr, "Cannot operate on left type");
}
if (!(rightType.as.success.type == STT_INT || rightType.as.success.type == STT_DOUBLE)) {
return Error(SolsType, charptr, "Cannot operate on right type");
}
if (leftType.as.success.type == rightType.as.success.type) {
return Success(SolsType, charptr, leftType.as.success);
}
ResultType(SolsType, charptr) type = createSolsType(STT_DOUBLE);
if (type.error) {
return Error(SolsType, charptr, type.as.error);
}
return Success(SolsType, charptr, type.as.success);
}
case SNT_LITERAL: {
switch (node->as.literal.type) {
case SLT_INT: {
@@ -179,6 +212,96 @@ static inline ResultType(GroundProgram, charptr) generateAddNode(SolsNode* node,
return Success(GroundProgram, charptr, gp);
}
static inline ResultType(GroundProgram, charptr) generateSubNode(SolsNode* node, SolsScope* scope) {
if (node->children.count < 2) {
return Error(GroundProgram, charptr, "sub requires arguments");
}
// Use this function for type checking
ResultType(SolsType, charptr) type = getNodeType(node, scope);
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
GroundProgram gp = groundCreateProgram();
GroundInstruction add = groundCreateInstruction(SUBTRACT);
groundAddReferenceToInstruction(&add, node->children.at[0].accessArg);
groundAddReferenceToInstruction(&add, node->children.at[1].accessArg);
char* tmpId = malloc(sizeof(char) * 64);
if (tmpId == NULL) {
return Error(GroundProgram, charptr, "Failed to allocate memory for temporary identifier in subtract");
}
snprintf(tmpId, 64, "__SOLS_TMP_SUB_%zu", scope->tmpCounter++);
groundAddReferenceToInstruction(&add, groundCreateReference(DIRREF, tmpId));
node->accessArg = groundCreateReference(VALREF, tmpId);
groundAddInstructionToProgram(&gp, add);
return Success(GroundProgram, charptr, gp);
}
static inline ResultType(GroundProgram, charptr) generateMulNode(SolsNode* node, SolsScope* scope) {
if (node->children.count < 2) {
return Error(GroundProgram, charptr, "mul requires arguments");
}
// Use this function for type checking
ResultType(SolsType, charptr) type = getNodeType(node, scope);
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
GroundProgram gp = groundCreateProgram();
GroundInstruction add = groundCreateInstruction(MULTIPLY);
groundAddReferenceToInstruction(&add, node->children.at[0].accessArg);
groundAddReferenceToInstruction(&add, node->children.at[1].accessArg);
char* tmpId = malloc(sizeof(char) * 64);
if (tmpId == NULL) {
return Error(GroundProgram, charptr, "Failed to allocate memory for temporary identifier in multiply");
}
snprintf(tmpId, 64, "__SOLS_TMP_MUL_%zu", scope->tmpCounter++);
groundAddReferenceToInstruction(&add, groundCreateReference(DIRREF, tmpId));
node->accessArg = groundCreateReference(VALREF, tmpId);
groundAddInstructionToProgram(&gp, add);
return Success(GroundProgram, charptr, gp);
}
static inline ResultType(GroundProgram, charptr) generateDivNode(SolsNode* node, SolsScope* scope) {
if (node->children.count < 2) {
return Error(GroundProgram, charptr, "div requires arguments");
}
// Use this function for type checking
ResultType(SolsType, charptr) type = getNodeType(node, scope);
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
GroundProgram gp = groundCreateProgram();
GroundInstruction add = groundCreateInstruction(DIVIDE);
groundAddReferenceToInstruction(&add, node->children.at[0].accessArg);
groundAddReferenceToInstruction(&add, node->children.at[1].accessArg);
char* tmpId = malloc(sizeof(char) * 64);
if (tmpId == NULL) {
return Error(GroundProgram, charptr, "Failed to allocate memory for temporary identifier in divide");
}
snprintf(tmpId, 64, "__SOLS_TMP_DIV_%zu", scope->tmpCounter++);
groundAddReferenceToInstruction(&add, groundCreateReference(DIRREF, tmpId));
node->accessArg = groundCreateReference(VALREF, tmpId);
groundAddInstructionToProgram(&gp, add);
return Success(GroundProgram, charptr, gp);
}
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
GroundProgram program = groundCreateProgram();
@@ -200,6 +323,9 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
case SNT_LITERAL: generate(Literal);
case SNT_OP_SET: generate(Set);
case SNT_OP_ADD: generate(Add);
case SNT_OP_SUB: generate(Sub);
case SNT_OP_MUL: generate(Mul);
case SNT_OP_DIV: generate(Div);
}
return Success(GroundProgram, charptr, program);
}