2026-02-24 20:07:02 +11:00
|
|
|
#include "codegen.h"
|
|
|
|
|
|
2026-02-24 21:01:30 +11:00
|
|
|
#include "SolsScope.h"
|
|
|
|
|
|
2026-02-24 20:07:02 +11:00
|
|
|
#include <groundvm.h>
|
2026-02-24 21:01:30 +11:00
|
|
|
|
2026-02-24 20:07:02 +11:00
|
|
|
#include "../parser/SolsNode.h"
|
|
|
|
|
#include "../include/estr.h"
|
2026-02-24 21:01:30 +11:00
|
|
|
#include "../include/uthash.h"
|
2026-02-24 20:07:02 +11:00
|
|
|
|
|
|
|
|
// FIXME add proper erroring function
|
|
|
|
|
char* createCodegenError(char* what) {
|
|
|
|
|
Estr estr = CREATE_ESTR(what);
|
|
|
|
|
APPEND_ESTR(estr, "\nthats an error");
|
|
|
|
|
return estr.str;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-25 21:44:55 +11:00
|
|
|
ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
|
|
|
|
switch (node->type) {
|
|
|
|
|
case SNT_PUTS: {
|
|
|
|
|
return Error(SolsType, charptr, "Specified node does not return data");
|
|
|
|
|
}
|
|
|
|
|
case SNT_OP_SET: {
|
|
|
|
|
if (node->children.count < 2) {
|
|
|
|
|
return Error(SolsType, charptr, "Not enough children to determine type");
|
|
|
|
|
}
|
|
|
|
|
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
|
|
|
|
if (type.error) {
|
|
|
|
|
return Error(SolsType, charptr, type.as.error);
|
|
|
|
|
}
|
|
|
|
|
return Success(SolsType, charptr, type.as.success);
|
|
|
|
|
}
|
2026-02-26 11:46:29 +11:00
|
|
|
case SNT_OP_ADD: {
|
|
|
|
|
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 || leftType.as.success.type == STT_STRING)) {
|
|
|
|
|
return Error(SolsType, charptr, "Cannot add left type");
|
|
|
|
|
}
|
|
|
|
|
if (!(rightType.as.success.type == STT_INT || rightType.as.success.type == STT_DOUBLE || rightType.as.success.type == STT_STRING)) {
|
|
|
|
|
return Error(SolsType, charptr, "Cannot add right type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (leftType.as.success.type == rightType.as.success.type) {
|
|
|
|
|
return Success(SolsType, charptr, leftType.as.success);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((leftType.as.success.type == STT_INT && rightType.as.success.type == STT_DOUBLE) || (leftType.as.success.type == STT_DOUBLE && rightType.as.success.type == STT_INT)) {
|
|
|
|
|
ResultType(SolsType, charptr) type = createSolsType(STT_DOUBLE);
|
|
|
|
|
if (type.error) {
|
|
|
|
|
return Error(SolsType, charptr, type.as.error);
|
|
|
|
|
}
|
|
|
|
|
return Success(SolsType, charptr, type.as.success);
|
|
|
|
|
}
|
|
|
|
|
return Error(SolsType, charptr, "Cannot add these types together");
|
|
|
|
|
}
|
2026-02-26 18:06:41 +11:00
|
|
|
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);
|
|
|
|
|
}
|
2026-02-27 14:54:16 +11:00
|
|
|
case SNT_OP_EQUAL: {
|
|
|
|
|
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_FUN || leftType.as.success.type == STT_TEMPLATE || leftType.as.success.type == STT_OBJECT) {
|
|
|
|
|
return Error(SolsType, charptr, "Cannot compare with left type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rightType.as.success.type == STT_FUN || rightType.as.success.type == STT_TEMPLATE || rightType.as.success.type == STT_OBJECT) {
|
|
|
|
|
return Error(SolsType, charptr, "Cannot compare with right type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (leftType.as.success.type == rightType.as.success.type) {
|
|
|
|
|
return Success(SolsType, charptr, {STT_BOOL});
|
|
|
|
|
}
|
|
|
|
|
if ((leftType.as.success.type == STT_INT && rightType.as.success.type == STT_DOUBLE) || (rightType.as.success.type == STT_INT && leftType.as.success.type == STT_DOUBLE)) {
|
|
|
|
|
return Success(SolsType, charptr, {STT_BOOL});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Error(SolsType, charptr, "");
|
|
|
|
|
}
|
2026-02-25 21:44:55 +11:00
|
|
|
case SNT_LITERAL: {
|
|
|
|
|
switch (node->as.literal.type) {
|
|
|
|
|
case SLT_INT: {
|
|
|
|
|
return Success(SolsType, charptr, {STT_INT});
|
|
|
|
|
}
|
|
|
|
|
case SLT_DOUBLE: {
|
|
|
|
|
return Success(SolsType, charptr, {STT_DOUBLE});
|
|
|
|
|
}
|
|
|
|
|
case SLT_STRING: {
|
|
|
|
|
return Success(SolsType, charptr, {STT_STRING});
|
|
|
|
|
}
|
|
|
|
|
case SLT_BOOL: {
|
|
|
|
|
return Success(SolsType, charptr, {STT_BOOL});
|
|
|
|
|
}
|
|
|
|
|
case SLT_CHAR: {
|
|
|
|
|
return Success(SolsType, charptr, {STT_CHAR});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SNT_IDENTIFIER: {
|
|
|
|
|
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
|
|
|
|
if (var == NULL) {
|
|
|
|
|
Estr estr = CREATE_ESTR("Unable to find variable ");
|
|
|
|
|
APPEND_ESTR(estr, node->as.idName);
|
|
|
|
|
return Error(SolsType, charptr, estr.str);
|
|
|
|
|
}
|
|
|
|
|
return Success(SolsType, charptr, var->typeinfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Error(SolsType, charptr, "Not yet implemented");
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 21:01:30 +11:00
|
|
|
static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* node, SolsScope* scope) {
|
2026-02-24 20:07:02 +11:00
|
|
|
// We don't even need to do anything lmao
|
|
|
|
|
return Success(GroundProgram, charptr, groundCreateProgram());
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 21:01:30 +11:00
|
|
|
static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node, SolsScope* scope) {
|
2026-02-24 20:07:02 +11:00
|
|
|
if (node->children.count < 1) {
|
|
|
|
|
return Error(GroundProgram, charptr, "puts requires arguments");
|
|
|
|
|
}
|
|
|
|
|
GroundInstruction inst = groundCreateInstruction(PRINTLN);
|
|
|
|
|
for (size_t i = 0; i < node->children.count; i++) {
|
|
|
|
|
groundAddReferenceToInstruction(&inst, node->children.at[i].accessArg);
|
|
|
|
|
}
|
|
|
|
|
GroundProgram program = groundCreateProgram();
|
|
|
|
|
groundAddInstructionToProgram(&program, inst);
|
|
|
|
|
return Success(GroundProgram, charptr, program);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 21:22:50 +11:00
|
|
|
static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node, SolsScope* scope) {
|
2026-02-25 21:44:55 +11:00
|
|
|
if (node->children.count < 2) {
|
2026-02-24 21:22:50 +11:00
|
|
|
return Error(GroundProgram, charptr, "set requires arguments");
|
|
|
|
|
}
|
2026-02-25 21:44:55 +11:00
|
|
|
if (node->children.at[0].type != SNT_IDENTIFIER) {
|
|
|
|
|
return Error(GroundProgram, charptr, "set requires an identifier before '='");
|
|
|
|
|
}
|
|
|
|
|
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
|
|
|
|
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[1], scope);
|
|
|
|
|
if (type.error) {
|
|
|
|
|
return Error(GroundProgram, charptr, type.as.error);
|
|
|
|
|
}
|
|
|
|
|
if (var == NULL) {
|
|
|
|
|
addVariableToScope(scope, node->children.at[0].as.idName, type.as.success);
|
|
|
|
|
} else {
|
|
|
|
|
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
|
|
|
|
if (type.error) {
|
|
|
|
|
return Error(GroundProgram, charptr, type.as.error);
|
|
|
|
|
}
|
|
|
|
|
if (compareTypes(&var->typeinfo, &type.as.success) == false) {
|
|
|
|
|
return Error(GroundProgram, charptr, "Type of variable cannot be changed");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
addVariableToScope(scope, node->children.at[0].as.idName, type.as.success);
|
|
|
|
|
|
|
|
|
|
GroundProgram gp = groundCreateProgram();
|
|
|
|
|
GroundInstruction gi = groundCreateInstruction(SET);
|
|
|
|
|
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].as.idName));
|
|
|
|
|
groundAddReferenceToInstruction(&gi, node->children.at[1].accessArg);
|
|
|
|
|
groundAddInstructionToProgram(&gp, gi);
|
|
|
|
|
|
|
|
|
|
return Success(GroundProgram, charptr, gp);
|
2026-02-24 21:22:50 +11:00
|
|
|
}
|
|
|
|
|
|
2026-02-26 11:46:29 +11:00
|
|
|
static inline ResultType(GroundProgram, charptr) generateAddNode(SolsNode* node, SolsScope* scope) {
|
|
|
|
|
if (node->children.count < 2) {
|
|
|
|
|
return Error(GroundProgram, charptr, "add 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(ADD);
|
|
|
|
|
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 add");
|
|
|
|
|
}
|
|
|
|
|
snprintf(tmpId, 64, "__SOLS_TMP_ADD_%zu", scope->tmpCounter++);
|
|
|
|
|
|
|
|
|
|
groundAddReferenceToInstruction(&add, groundCreateReference(DIRREF, tmpId));
|
|
|
|
|
|
|
|
|
|
node->accessArg = groundCreateReference(VALREF, tmpId);
|
|
|
|
|
|
|
|
|
|
groundAddInstructionToProgram(&gp, add);
|
|
|
|
|
return Success(GroundProgram, charptr, gp);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-26 18:06:41 +11:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 14:54:16 +11:00
|
|
|
static inline ResultType(GroundProgram, charptr) generateEqualNode(SolsNode* node, SolsScope* scope) {
|
|
|
|
|
if (node->children.count < 2) {
|
|
|
|
|
return Error(GroundProgram, charptr, "equal 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(EQUAL);
|
|
|
|
|
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 equal");
|
|
|
|
|
}
|
|
|
|
|
snprintf(tmpId, 64, "__SOLS_TMP_EQUAL_%zu", scope->tmpCounter++);
|
|
|
|
|
|
|
|
|
|
groundAddReferenceToInstruction(&add, groundCreateReference(DIRREF, tmpId));
|
|
|
|
|
|
|
|
|
|
node->accessArg = groundCreateReference(VALREF, tmpId);
|
|
|
|
|
|
|
|
|
|
groundAddInstructionToProgram(&gp, add);
|
|
|
|
|
return Success(GroundProgram, charptr, gp);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 21:01:30 +11:00
|
|
|
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
2026-02-24 20:07:02 +11:00
|
|
|
|
|
|
|
|
GroundProgram program = groundCreateProgram();
|
|
|
|
|
|
|
|
|
|
// Generate code for all children before generating this node's code
|
|
|
|
|
for (size_t i = 0; i < node->children.count; i++) {
|
2026-02-24 21:01:30 +11:00
|
|
|
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i], scope);
|
2026-02-24 20:07:02 +11:00
|
|
|
if (generated.error) {
|
|
|
|
|
return Error(GroundProgram, charptr, createCodegenError(generated.as.error));
|
|
|
|
|
}
|
|
|
|
|
for (size_t j = 0; j < generated.as.success.size; j++) {
|
|
|
|
|
groundAddInstructionToProgram(&program, generated.as.success.instructions[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now generate code for this node
|
|
|
|
|
switch (node->type) {
|
|
|
|
|
case SNT_PUTS: generate(Puts);
|
|
|
|
|
case SNT_LITERAL: generate(Literal);
|
2026-02-24 21:22:50 +11:00
|
|
|
case SNT_OP_SET: generate(Set);
|
2026-02-26 11:46:29 +11:00
|
|
|
case SNT_OP_ADD: generate(Add);
|
2026-02-26 18:06:41 +11:00
|
|
|
case SNT_OP_SUB: generate(Sub);
|
|
|
|
|
case SNT_OP_MUL: generate(Mul);
|
|
|
|
|
case SNT_OP_DIV: generate(Div);
|
2026-02-27 14:54:16 +11:00
|
|
|
case SNT_OP_EQUAL: generate(Equal);
|
2026-02-24 20:07:02 +11:00
|
|
|
}
|
|
|
|
|
return Success(GroundProgram, charptr, program);
|
|
|
|
|
}
|