+#include "vm_generator.h"
+
+#include <sun/tree/node_internal.h>
+#include <sun/tree/node_type.h>
+#include <sun/tree/tree.h>
+#include <sun/vm/instruction.h>
+#include <sun/vm/vm_internal.h>
+
+
+#include <stdarg.h> //fixme
+#include <stdbool.h> //fixme
+#include <stdlib.h> //fixme
+#include <stdio.h> //fixme
+#include <string.h> //fixme
+
+#define generator_assert_msg(t,m,...) if(!(t)) { fprintf(stderr,"%s:%u ERROR:"m"\n",__FILE__,__LINE__, ##__VA_ARGS__); exit(1); }
+#define generator_assert(t) generator_assert_msg(t,"invalid")
+
+struct VMGeneratorInstruction {
+ SVMInstruction instruction;
+};
+
+struct VMGeneratorOutputScope {
+ char *stringClump;
+ size_t stringClumpSize;
+ size_t stringClumpMaxSize;
+
+ struct VMGeneratorInstruction *instructions;
+ size_t instructionCount;
+ SVMPointer nextInstructionIdx;
+
+ struct VMGeneratorInstruction *resolvableDefinition;
+};
+typedef struct VMGeneratorOutputScope VMGeneratorOutputScope;
+
+enum VMNodeMetadataIdentifierType {
+ VMNodeMetadataIdentifierTypeUnknown,
+ VMNodeMetadataIdentifierTypeNullType,
+ VMNodeMetadataIdentifierTypeIntegerType,
+ VMNodeMetadataIdentifierTypeFloatType,
+ VMNodeMetadataIdentifierTypeStringType,
+ //VMNodeMetadataIdentifierTypeUserType,
+ VMNodeMetadataIdentifierTypeVariable,
+ VMNodeMetadataIdentifierTypeFunction,
+ VMNodeMetadataIdentifierTypeParameter,
+};
+typedef enum VMNodeMetadataIdentifierType VMNodeMetadataIdentifierType;
+
+struct VMNodeMetadata {
+ struct {
+ bool definesScope;
+ bool holdsVariableScope;
+ SLTNode *parentScope;
+ SLTNode *scopedFunctionsHead;
+ SLTNode *scopedVariablesHead;
+ SLTNode *scopedParametersHead;
+ SLTNode *scopedBreaksHead;
+ } scope;
+
+ struct {
+ SVMPointer address;
+ SLTNode *scopedFunctionNext;
+ } function;
+
+ struct {
+ SLTNode *scopedVariableNext;
+ } variable;
+
+ struct {
+ SLTNode *scopedParameterNext;
+ } parameter;
+
+ struct {
+ SVMPointer breakInstruction;
+ SLTNode *scopedBreakNext;
+ } breakStatement;
+
+ struct {
+ VMNodeMetadataIdentifierType type;
+ SLTNode *resolvedNode;
+ } identifier;
+
+ struct {
+ SVMStackOffset offset;
+ } stack;
+
+ struct {
+ SVMPointer address;
+ } string;
+
+ struct {
+ bool native;
+ SVMPointer instruction;
+ } functionCall;
+};
+typedef struct VMNodeMetadata VMNodeMetadata;
+
+union VMGeneratorVisitor {
+ VMGeneratorOutputScope *generator;
+ SLTNode *currentScope;
+ struct {
+ bool typeChanged;
+ bool typeUnresolved;
+ };
+};
+typedef union VMGeneratorVisitor VMGeneratorVisitor;
+
+
+#define sltGetNodeMetadata(node) ((VMNodeMetadata *)(node)->metadata)
+
+
+
+static VMGeneratorOutputScope *generatorCreate() {
+ VMGeneratorOutputScope *scope = malloc(sizeof(VMGeneratorOutputScope)); // fixme these mallocs
+ memset(scope, 0, sizeof(VMGeneratorOutputScope));
+
+ scope->instructionCount = 1024;
+ scope->instructions = malloc(scope->instructionCount * sizeof(struct VMGeneratorInstruction));
+ scope->nextInstructionIdx = 0;
+
+ scope->stringClumpMaxSize = 1024;
+ scope->stringClump = malloc(scope->stringClumpMaxSize);
+ scope->stringClumpSize = 0;
+
+ return scope;
+}
+
+
+
+static size_t opcodeOperandCount(SVMOpcode opcode) {
+ switch (opcode) {
+ case SVMOpcodeSLEEP:
+ case SVMOpcodePOPJUMP:
+ return 0;
+
+ case SVMOpcodeSTK:
+ case SVMOpcodeJUMP:
+ case SVMOpcodePUSHJUMP:
+ return 1;
+
+ case SVMOpcodeMOV:
+ case SVMOpcodeSET:
+ case SVMOpcodeINV:
+ case SVMOpcodeBNOT:
+ case SVMOpcodeNOT:
+ case SVMOpcodeJT:
+ case SVMOpcodeCALL:
+ return 2;
+
+ case SVMOpcodeADD:
+ case SVMOpcodeSUB:
+ case SVMOpcodeMUL:
+ case SVMOpcodeDIV:
+ case SVMOpcodeMOD:
+ case SVMOpcodeBAND:
+ case SVMOpcodeBOR:
+ case SVMOpcodeBXOR:
+ case SVMOpcodeAND:
+ case SVMOpcodeOR:
+ case SVMOpcodeEQ:
+ case SVMOpcodeNEQ:
+ case SVMOpcodeLT:
+ case SVMOpcodeLTEQ:
+ case SVMOpcodeGT:
+ case SVMOpcodeGTEQ:
+ return 3;
+
+ default:
+ generator_assert_msg(false, "invalid opcode %u", opcode);
+ return -1;
+ }
+}
+
+
+static SVMPointer generatorNextInstruction(VMGeneratorOutputScope *generator) {
+ generator_assert(generator->nextInstructionIdx < generator->instructionCount);
+ SVMPointer idx = generator->nextInstructionIdx;
+ return idx;
+}
+
+static SVMPointer generatorAddInstruction(VMGeneratorOutputScope *generator, SVMOpcode opcode, ...) {
+ generator_assert(generator->nextInstructionIdx < generator->instructionCount);
+
+ SVMPointer idx = generatorNextInstruction(generator);
+ generator->nextInstructionIdx++;
+ struct VMGeneratorInstruction *instruction = &generator->instructions[idx];
+
+ instruction->instruction.opcode = opcode;
+
+ size_t numOperands = opcodeOperandCount(opcode);
+
+ va_list args;
+ va_start(args, opcode);
+ for (size_t i = 0; i < numOperands; ++i) {
+ instruction->instruction.operands[i] = va_arg(args, SVMOperand);
+ }
+ va_end(args);
+
+ return idx;
+}
+
+static void generatorPatchOperand(VMGeneratorOutputScope *generator, SVMPointer instruction, size_t idx, SVMOperand value) {
+ generator_assert(instruction < generator->instructionCount);
+ generator_assert_msg(idx < opcodeOperandCount(generator->instructions[instruction].instruction.opcode), "invalid idx");
+ generator->instructions[instruction].instruction.operands[idx] = value;
+}
+
+static SVMPointer generatorAddString(VMGeneratorOutputScope *generator, const char *string) {
+ char *ptr = generator->stringClump;
+
+ while (ptr < generator->stringClump + generator->stringClumpSize) {
+ //printf("testing string: %s == %s\n", ptr, string);
+ if (strcmp(string, ptr) == 0) {
+ return ptr - generator->stringClump;
+ }
+ ptr+=strlen(ptr) + 1;
+ }
+
+ size_t stringLength = strlen(string) + 1;
+ generator_assert_msg(ptr + stringLength <= generator->stringClump + generator->stringClumpMaxSize, "out of string space!!!");
+
+ strcpy(ptr, string);
+ generator->stringClumpSize += stringLength;
+
+ //printf("added string: %s\n", string);
+
+ return ptr - generator->stringClump;
+}
+
+static SVMStackOffset generatorResolveIdentifier(VMGeneratorOutputScope *generator, SLTNode *node) {
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+ generator_assert_msg(metadata->identifier.type != VMNodeMetadataIdentifierTypeUnknown, "could not resolve %s", node->identifierStringValue);
+ SVMStackOffset offset = sltGetNodeMetadata(metadata->identifier.resolvedNode)->stack.offset;
+ return offset;
+}
+
+
+static SVMModule *generatorFinalize(VMGeneratorOutputScope *generator) {
+ size_t memorySize = sizeof(SVMModule) + generator->stringClumpSize + /*0 * sizeof(SVMModuleFunctionDetails) +*/ generator->nextInstructionIdx * sizeof(SVMInstruction);
+
+ SVMModule *module = (SVMModule *)malloc(memorySize);
+ module->header[0] = 's';
+ module->header[1] = 'u';
+ module->header[2] = 'n';
+ module->header[3] = 'l';
+ module->magic = 1525;
+ module->stringBlobLength = generator->stringClumpSize;
+ module->numFunctions = 0; // FIXME
+ module->numInstructions = generator->nextInstructionIdx;
+
+ memcpy((void *)module + sizeof(SVMModule), generator->stringClump, module->stringBlobLength);
+ // COPY FUNCTIONS HERE...
+ memcpy((void *)module + sizeof(SVMModule) + module->stringBlobLength, generator->instructions, module->numInstructions * sizeof(SVMInstruction));
+
+ return module;
+}
+
+
+
+
+static void addNodeMetadata(SLTNode *node, void *userParameter) {
+ VMNodeMetadata *metadata = (VMNodeMetadata *)malloc(sizeof(VMNodeMetadata));// fixme
+ memset(metadata, 0, sizeof(VMNodeMetadata));
+ node->metadata = metadata;
+}
+
+
+static void findStrings(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeString:
+ metadata->string.address = generatorAddString(visitor->generator, node->stringValue);
+ break;
+
+ case SLTNodeTypeFunctionCall:
+ metadata->string.address = generatorAddString(visitor->generator, node->functionCallFunction->identifierStringValue);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+static bool nodeTypeDefinesScope(SLTNodeType type) {
+ switch (type) {
+ case SLTNodeTypeModule:
+ case SLTNodeTypeFunctionDefinition:
+ case SLTNodeTypeTypeDefinition:
+ case SLTNodeTypeForIteration:
+ case SLTNodeTypeDoIteration:
+ case SLTNodeTypeWhileIteration:
+ case SLTNodeTypeStatementBlock:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool nodeTypeHoldsVariables(SLTNodeType type) {
+ switch (type) {
+ case SLTNodeTypeModule:
+ case SLTNodeTypeFunctionDefinition:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static void beginScopeNode(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ metadata->scope.parentScope = visitor->currentScope;
+
+ if (nodeTypeDefinesScope(node->type)) {
+ metadata->scope.definesScope = true;
+ metadata->scope.holdsVariableScope = nodeTypeHoldsVariables(node->type);
+ visitor->currentScope = node;
+ }
+}
+
+static void endScopeNode(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ if (nodeTypeDefinesScope(node->type)) {
+ visitor->currentScope = metadata->scope.parentScope;
+ }
+}
+
+static SLTNode *findScope(SLTNode *node) {
+ while (sltGetNodeMetadata(node)->scope.definesScope == false) {
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+ node = metadata->scope.parentScope;
+ generator_assert_msg(node != NULL, "failed to scope"); // FIXME
+ }
+
+ return node;
+}
+
+static SLTNode *findContainingScope(SLTNode *node) {
+ for (;;) {
+ node = findScope(node);
+
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+ if (metadata->scope.holdsVariableScope) {
+ return node;
+ }
+
+ node = metadata->scope.parentScope;
+
+ generator_assert_msg(node != NULL, "failed to scope"); // FIXME
+ }
+}
+
+static void scopeDefinitions(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeFunctionParameterDefinition: {
+ //printf("def parameter %s\n", node->functionParameterDefinitionIdentifier->stringValue);
+ VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findContainingScope(node));
+ metadata->parameter.scopedParameterNext = scopeMetadata->scope.scopedParametersHead;
+ scopeMetadata->scope.scopedParametersHead = node;
+ break;
+ }
+
+ case SLTNodeTypeVariableDefinition: {
+ //printf("def var %s\n", node->variableDefinitionIdentifier->stringValue);
+ VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findContainingScope(node));
+ metadata->variable.scopedVariableNext = scopeMetadata->scope.scopedVariablesHead;
+ scopeMetadata->scope.scopedVariablesHead = node;
+ break;
+ }
+
+ case SLTNodeTypeFunctionDefinition: {
+ //printf("def func %s\n", node->functionDefinitionIdentifier->stringValue);
+ VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findScope((sltGetNodeMetadata(findScope(node))->scope.parentScope))); // Functions define a scope...
+ metadata->function.scopedFunctionNext = scopeMetadata->scope.scopedFunctionsHead;
+ scopeMetadata->scope.scopedFunctionsHead = node;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+static SLTNode *resolveDefinition(VMNodeMetadataIdentifierType *typeOut, SLTNode *node, const char *name) {
+ if (strcmp(name, "void") == 0) { // FIXME, can de-duplicate these for speed earlier..
+ *typeOut = VMNodeMetadataIdentifierTypeNullType;
+ return NULL;
+ }
+
+ if (strcmp(name, "int") == 0) {
+ *typeOut = VMNodeMetadataIdentifierTypeIntegerType;
+ return NULL;
+ }
+
+ if (strcmp(name, "float") == 0) {
+ *typeOut = VMNodeMetadataIdentifierTypeFloatType;
+ return NULL;
+ }
+
+ if (strcmp(name, "string") == 0) {
+ *typeOut = VMNodeMetadataIdentifierTypeStringType;
+ return NULL;
+ }
+
+ for (;;) {
+ VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findScope(node));
+
+ // Should do types here...
+
+ for (SLTNode *n = scopeMetadata->scope.scopedFunctionsHead; n != NULL; n = sltGetNodeMetadata(n)->function.scopedFunctionNext) {
+ if (strcmp(n->functionDefinitionIdentifier->identifierStringValue, name) == 0) {
+ *typeOut = VMNodeMetadataIdentifierTypeFunction;
+ //printf("GOT F %s\n", name);
+ return n;
+ }
+ }
+
+ for (SLTNode *n = scopeMetadata->scope.scopedVariablesHead; n != NULL; n = sltGetNodeMetadata(n)->variable.scopedVariableNext) {
+ if (strcmp(n->variableDefinitionIdentifier->identifierStringValue, name) == 0) {
+ *typeOut = VMNodeMetadataIdentifierTypeVariable;
+ //printf("GOT V %s\n", name);
+ return n;
+ }
+ }
+
+ for (SLTNode *n = scopeMetadata->scope.scopedParametersHead; n != NULL; n = sltGetNodeMetadata(n)->parameter.scopedParameterNext) {
+ if (strcmp(n->functionParameterDefinitionIdentifier->identifierStringValue, name) == 0) {
+ *typeOut = VMNodeMetadataIdentifierTypeParameter;
+ //printf("GOT P %s\n", name);
+ return n;
+ }
+ }
+
+ if (scopeMetadata->scope.parentScope != NULL) {
+ node = scopeMetadata->scope.parentScope;
+ } else {
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static void resolveDefinitions(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeIdentifier:
+ metadata->identifier.resolvedNode = resolveDefinition(&metadata->identifier.type, node, node->identifierStringValue);
+ //printf("trying to get %s %x\n", node->stringValue, metadata->identifier.resolvedNode);
+ //metadata->variable.scopedVariableNext = metadata->scope.scopedVariablesHead;
+ //metadata->scope.scopedVariablesHead = node;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void resolveDefinitionsNativeFunctions(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeFunctionCall:
+ if (sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode == NULL) {
+ metadata->functionCall.instruction = node->functionCallFunction->identifierStringKeyValue;
+ metadata->functionCall.native = true;
+ }
+
+ default:
+ break;
+ }
+}
+
+
+
+static void indexDefinitions(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ // Functions put their return value at the 0th stack position, modules start at -1
+ size_t idx = 1;
+
+ size_t parameterCount = 0;
+ for (SLTNode *parameter = metadata->scope.scopedParametersHead; parameter != NULL; ++parameterCount, parameter = sltGetNodeMetadata(parameter)->parameter.scopedParameterNext);
+
+ SLTNode *parameter = metadata->scope.scopedParametersHead;
+ while (parameter != NULL) {
+ sltGetNodeMetadata(parameter)->stack.offset = node->type == SLTNodeTypeModule ? -idx : (parameterCount + 1) - idx; // Parameter positions are inverted...
+ ++idx;
+ parameter = sltGetNodeMetadata(parameter)->parameter.scopedParameterNext;
+ }
+
+ SLTNode *variable = metadata->scope.scopedVariablesHead;
+ while (variable != NULL) {
+ sltGetNodeMetadata(variable)->stack.offset = node->type == SLTNodeTypeModule ? -idx : idx;
+ ++idx;
+ variable = sltGetNodeMetadata(variable)->variable.scopedVariableNext;
+ }
+}
+
+
+
+/*static void resolveTypes(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeUnknown:
+ case SLTNodeTypeSequence:
+ generator_assert_msg(false, "unexpected: %s", sltNodeToString(node));// fixme
+ break;
+
+ case SLTNodeTypeIdentifier:
+ // ...??
+
+ case SLTNodeTypeBoolean:
+ case SLTNodeTypeInteger:
+ case SLTNodeTypeFloat:
+ case SLTNodeTypeString:
+
+ case SLTNodeTypeCompound:
+
+ case SLTNodeTypeArgument:
+
+ case SLTNodeTypeArrayAccess:
+ case SLTNodeTypeTypeAccess:
+
+ case SLTNodeTypeFunctionCall:
+
+ case SLTNodeTypeUnaryOperation:
+ case SLTNodeTypeBinaryOperation:
+
+ case SLTNodeTypeOperator:
+
+ case SLTNodeTypeAssignment:
+
+ case SLTNodeTypeReturn:
+ case SLTNodeTypeSleep:
+
+ case SLTNodeTypeForIteration:
+ case SLTNodeTypeDoIteration:
+ case SLTNodeTypeWhileIteration:
+
+ case SLTNodeTypeSelection:
+
+ case SLTNodeTypeStatementBlock:
+
+ case SLTNodeTypeVariableDefinition:
+
+ case SLTNodeTypeTypeDefinition:
+ case SLTNodeTypeTypeMemberDefinition:
+
+ case SLTNodeTypeFunctionDefinition:
+ case SLTNodeTypeFunctionParameterDefinition:
+
+ case SLTNodeTypeModule:
+
+
+ }
+
+visitor.typeChanged = false;
+
+
+
+
+
+
+ if (node->dataType == SLTDataTypeUnknown) {
+ visitor->typeUnresolved = true;
+ }
+}*/
+
+static bool nodeTypeIsLoop(SLTNodeType type) {
+ switch (type) {
+ case SLTNodeTypeForIteration:
+ case SLTNodeTypeDoIteration:
+ case SLTNodeTypeWhileIteration:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static SLTNode *findLoopScope(SLTNode *node) {
+ for (;;) {
+ node = findScope(node);
+
+ if (nodeTypeIsLoop(node->type)) {
+ return node;
+ }
+
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+ node = metadata->scope.parentScope;
+
+ generator_assert_msg(node != NULL, "failed to scope loop"); // FIXME
+ }
+}
+
+static void scopeIterationBreaks(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeBreak: {
+ VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findLoopScope(node));
+ metadata->breakStatement.scopedBreakNext = scopeMetadata->scope.scopedBreaksHead;
+ scopeMetadata->scope.scopedBreaksHead = node;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+
+static SVMPointer generateValueInstructions(VMGeneratorOutputScope *generator, SLTNode *node, SVMOperand target) {
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeIdentifier: {
+ SVMOperand source = { .stackOffset = generatorResolveIdentifier(generator, node) };
+ return generatorAddInstruction(generator, SVMOpcodeMOV, target, source);
+ }
+
+ case SLTNodeTypeBoolean: {
+ SVMOperand source = { .integerLiteral = node->booleanValue ? 1 : 0 };
+ return generatorAddInstruction(generator, SVMOpcodeSET, target, source);
+ }
+
+ case SLTNodeTypeInteger: {
+ SVMOperand source = { .integerLiteral = FIXED(node->integerValue) };
+ return generatorAddInstruction(generator, SVMOpcodeSET, target, source);
+ }
+
+ case SLTNodeTypeRawInteger: {
+ SVMOperand source = { .__raw = node->integerValue };
+ return generatorAddInstruction(generator, SVMOpcodeSET, target, source);
+ }
+
+ case SLTNodeTypeFloat: {
+ SVMOperand source = { .floatLiteral = FIXED_FROM_FLOAT(node->floatValue) };
+ return generatorAddInstruction(generator, SVMOpcodeSET, target, source);
+ }
+
+ case SLTNodeTypeString: {
+ SVMOperand source = { .pointerLiteral = metadata->string.address }; // FIXME, string pool needed
+ return generatorAddInstruction(generator, SVMOpcodeSET, target, source);
+ }
+
+ case SLTNodeTypeKey: {
+ SVMOperand source = { .pointerLiteral = node->keyValue };
+ return generatorAddInstruction(generator, SVMOpcodeSET, target, source);
+ }
+
+ default:
+ generator_assert_msg(false, "unexpected: %s", sltNodeToString(node));// fixme
+ return -1; // FIXME
+ }
+}
+
+static SVMPointer generateExpressionInstructions(VMGeneratorOutputScope *generator, SLTNode *node, SVMOperand target, SVMStackOffset workingStackOffset) {
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ switch (node->type) {
+ case SLTNodeTypeBinaryOperation: {
+ SVMOperand lhsOperand = { .stackOffset = workingStackOffset };
+ generateExpressionInstructions(generator, node->binaryOperationLHS, lhsOperand, workingStackOffset + 1);
+
+ SVMOperand rhsOperand = { .stackOffset = workingStackOffset + 1 };
+ generateExpressionInstructions(generator, node->binaryOperationRHS, rhsOperand, workingStackOffset + 2);
+
+ switch (node->binaryOperationOperator->operatorType) {
+ case SLTOperatorTypeAdd:
+ return generatorAddInstruction(generator, SVMOpcodeADD, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeSubtract:
+ return generatorAddInstruction(generator, SVMOpcodeSUB, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeMultiply:
+ return generatorAddInstruction(generator, SVMOpcodeMUL, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeDivide:
+ return generatorAddInstruction(generator, SVMOpcodeDIV, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeModulo:
+ return generatorAddInstruction(generator, SVMOpcodeMOD, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeBitwiseAnd:
+ return generatorAddInstruction(generator, SVMOpcodeBAND, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeBitwiseOr:
+ return generatorAddInstruction(generator, SVMOpcodeBOR, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeBitwiseXor:
+ return generatorAddInstruction(generator, SVMOpcodeBXOR, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeLogicalAnd:
+ return generatorAddInstruction(generator, SVMOpcodeAND, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeLogicalOr:
+ return generatorAddInstruction(generator, SVMOpcodeOR, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeEqual:
+ return generatorAddInstruction(generator, SVMOpcodeEQ, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeNotEqual:
+ return generatorAddInstruction(generator, SVMOpcodeNEQ, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeLessThan:
+ return generatorAddInstruction(generator, SVMOpcodeLT, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeLessThanEqual:
+ return generatorAddInstruction(generator, SVMOpcodeLTEQ, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeGreaterThan:
+ return generatorAddInstruction(generator, SVMOpcodeGT, target, lhsOperand, rhsOperand);
+
+ case SLTOperatorTypeGreaterThanEqual:
+ return generatorAddInstruction(generator, SVMOpcodeGTEQ, target, lhsOperand, rhsOperand);
+
+ default:
+ generator_assert_msg(false, "invalid binary operator %s", sltOperatorTypeToString(node->binaryOperationOperator->operatorType));
+ return -1;
+ }
+ }
+
+ case SLTNodeTypeUnaryOperation: {
+ SVMOperand operand = { .stackOffset = target.stackOffset };
+ generateExpressionInstructions(generator, node->unaryOperationOperand, operand, workingStackOffset);
+
+ switch (node->unaryOperationOperator->operatorType) {
+ //case SLTOperatorTypePositive:
+ // return -1;
+
+ case SLTOperatorTypeNegative:
+ return generatorAddInstruction(generator, SVMOpcodeINV, target, operand);
+
+ case SLTOperatorTypeBitwiseNot:
+ return generatorAddInstruction(generator, SVMOpcodeBNOT, target, operand);
+
+ case SLTOperatorTypeLogicalNot:
+ return generatorAddInstruction(generator, SVMOpcodeNOT, target, operand);
+
+ default:
+ generator_assert_msg(false, "invalid unary operator %s", sltOperatorTypeToString(node->unaryOperationOperator->operatorType));
+ return -1;
+ }
+ }
+
+ case SLTNodeTypeArrayAccess:
+ generator_assert_msg(false, "not implemented: %s", sltNodeToString(node));
+ return -1;
+
+ case SLTNodeTypeFunctionCall: {
+ //generator_assert_msg(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode != NULL, "unresolved function: %s", node->functionCallFunction->stringValue);// fixme
+
+ SVMPointer r = generatorNextInstruction(generator);
+
+ SVMInteger parameterCount = 0;
+ for (SLTNode *n = node->functionCallArguments; n != NULL; n = n->sequenceNext) {
+ ++parameterCount;
+ SVMStackOffset parameterTarget = workingStackOffset + parameterCount;
+ SVMOperand target = { .stackOffset = parameterTarget, };
+ generateExpressionInstructions(generator, n->sequenceNode->argumentExpression, target, parameterTarget);
+ }
+
+ // Offset the stack to make 0 where we're returning into...
+ SVMStackOffset stackOffset = workingStackOffset;// + parameterCount;
+ generatorAddInstruction(generator, SVMOpcodeSTK, stackOffset);
+
+ // Call the function
+ if (metadata->functionCall.native == false) {
+ metadata->functionCall.instruction = generatorAddInstruction(generator, SVMOpcodePUSHJUMP, 999); // Silly marker, we patch this later...
+ } else {
+ metadata->functionCall.instruction = generatorAddInstruction(generator, SVMOpcodeCALL, metadata->functionCall.instruction, parameterCount);
+ }
+
+ // Put the stack back
+ generatorAddInstruction(generator, SVMOpcodeSTK, -stackOffset);
+
+ // Move result
+ if (target.stackOffset != workingStackOffset) {
+ SVMOperand source = { .stackOffset = workingStackOffset };
+ generatorAddInstruction(generator, SVMOpcodeMOV, target, source);
+ }
+
+ return r;
+ }
+
+ case SLTNodeTypeTypeAccess:
+ generator_assert_msg(false, "not implemented: %s", sltNodeToString(node));
+ return -1;
+
+ case SLTNodeTypeCompound:
+ return generateExpressionInstructions(generator, node->compoundSubexpression, target, workingStackOffset);
+
+ default:
+ return generateValueInstructions(generator, node, target);
+ }
+}
+
+static SVMPointer generateStatementInstructions(VMGeneratorOutputScope *generator, SLTNode *node, SVMStackOffset workingStackOffset) {
+ switch (node->type) {
+ case SLTNodeTypeStatementBlock: {
+ SVMPointer r = generatorNextInstruction(generator);
+
+ // FIXME, call the function thing...
+ // FIXME, open some kind of scope??
+ for (SLTNode *n = node->statementBlockContents; n != NULL; n = n->sequenceNext) {
+ generateStatementInstructions(generator, n->sequenceNode, workingStackOffset);
+ }
+
+ return r;
+ }
+
+ case SLTNodeTypeVariableDefinition: {
+ SVMPointer r = generatorNextInstruction(generator);
+
+ if (node->variableDefinitionDefaultExpression != NULL) {
+ SVMOperand target = { .stackOffset = generatorResolveIdentifier(generator, node->variableDefinitionIdentifier), };
+ generateExpressionInstructions(generator, node->variableDefinitionDefaultExpression, target, workingStackOffset);
+ }
+
+ return r;
+ }
+
+ case SLTNodeTypeSelection: {
+ SVMPointer r = generatorNextInstruction(generator);
+
+ SVMOperand valid = { .stackOffset = 0, };
+ generateExpressionInstructions(generator, node->selectionValidExpression, valid, workingStackOffset + 1);
+ generatorAddInstruction(generator, SVMOpcodeNOT, valid, valid); // Inverse for this check...
+ SVMPointer patchPre = generatorAddInstruction(generator, SVMOpcodeJT, valid, 999);
+
+ if (node->selectionValidStatement != NULL) {
+ generateStatementInstructions(generator, node->selectionValidStatement, workingStackOffset);
+ }
+
+ if (node->selectionInvalidStatement != NULL) {
+ SVMPointer patchPost = generatorAddInstruction(generator, SVMOpcodeJUMP, 999);
+
+ SVMOperand target = { .pointerLiteral = generatorNextInstruction(generator), };
+ generatorPatchOperand(generator, patchPre, 1, target);
+
+ generateStatementInstructions(generator, node->selectionInvalidStatement, workingStackOffset);
+
+ target.pointerLiteral = generatorNextInstruction(generator);
+ generatorPatchOperand(generator, patchPost, 0, target);
+ } else {
+ SVMOperand target = { .pointerLiteral = generatorNextInstruction(generator), };
+ generatorPatchOperand(generator, patchPre, 1, target);
+ }
+
+ return r;
+ }
+
+ case SLTNodeTypeDoIteration:
+ case SLTNodeTypeForIteration:
+ case SLTNodeTypeWhileIteration: {
+ if (node->iterationInitialExpression != NULL) {
+ //SVMOperand target = { .stackOffset = 0, };
+ //generateExpressionInstructions(generator, node->iterationInitialExpression, target, workingStackOffset); // FIXME, is this a statement??
+ generateStatementInstructions(generator, node->iterationInitialExpression, workingStackOffset);
+ }
+
+ SVMPointer r = generatorNextInstruction(generator);
+
+ SVMPointer patchPre;
+ if (node->iterationPreValidExpression != NULL) {
+ SVMOperand valid = { .stackOffset = 0, };
+ generateExpressionInstructions(generator, node->iterationPreValidExpression, valid, workingStackOffset + 1);
+ generatorAddInstruction(generator, SVMOpcodeNOT, valid, valid); // Inverse for this check...
+ patchPre = generatorAddInstruction(generator, SVMOpcodeJT, valid, 999);
+ }
+
+ if (node->iterationStatement != NULL) {
+ generateStatementInstructions(generator, node->iterationStatement, workingStackOffset);
+ }
+
+ if (node->iterationLoopExpression != NULL) {
+ //SVMOperand target = { .stackOffset = 0, };
+ //generateExpressionInstructions(generator, node->iterationLoopExpression, target, workingStackOffset); // FIXME, is this a statement??
+ generateStatementInstructions(generator, node->iterationLoopExpression, workingStackOffset);
+ }
+
+ if (node->iterationPostValidExpression != NULL) {
+ SVMOperand valid = { .stackOffset = 0, };
+ generateExpressionInstructions(generator, node->iterationPostValidExpression, valid, workingStackOffset + 1);
+ generatorAddInstruction(generator, SVMOpcodeJT, valid, r);
+ } else {
+ generatorAddInstruction(generator, SVMOpcodeJUMP, r);
+ }
+
+ // Patch jump...
+ SVMOperand target = { .pointerLiteral = generatorNextInstruction(generator), };
+
+ if (node->iterationPreValidExpression != NULL) {
+ generatorPatchOperand(generator, patchPre, 1, target);
+ }
+
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+ for (SLTNode *v = metadata->scope.scopedBreaksHead; v != NULL; v = sltGetNodeMetadata(v)->breakStatement.scopedBreakNext) {
+ generatorPatchOperand(generator, sltGetNodeMetadata(v)->breakStatement.breakInstruction, 0, target);
+ }
+
+ return r;
+ }
+
+ case SLTNodeTypeAssignment: {
+ SVMOperand target = { .stackOffset = generatorResolveIdentifier(generator, node->assignmentTarget) };
+ return generateExpressionInstructions(generator, node->assignmentSource, target, workingStackOffset);
+ }
+
+ case SLTNodeTypeReturn: {
+ SVMPointer r = generatorNextInstruction(generator);
+
+ if (node->returnExpression != NULL) {
+ SVMOperand target = { .stackOffset = 0, }; // return is always at 0
+ generateExpressionInstructions(generator, node->returnExpression, target, workingStackOffset);
+ }
+ generatorAddInstruction(generator, SVMOpcodePOPJUMP);
+
+ return r;
+ }
+
+ case SLTNodeTypeSleep:
+ return generatorAddInstruction(generator, SVMOpcodeSLEEP);
+
+ case SLTNodeTypeBreak: {
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+ metadata->breakStatement.breakInstruction = generatorAddInstruction(generator, SVMOpcodeJUMP, 999);
+ return metadata->breakStatement.breakInstruction;
+ }
+
+ default: {
+// generator_assert_msg(false, "not implemented as statement: %s", sltNodeToString(node));
+ SVMOperand target = { .stackOffset = 0, }; // FIXME!!!
+ return generateExpressionInstructions(generator, node, target, workingStackOffset);
+ }
+ }
+}
+
+static void generateFunctionDefinitionInstructions(VMGeneratorOutputScope *generator, SLTNode *node) {
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ // count parameters, these are first on the stack...
+ size_t numParameters = 0;
+ for (SLTNode *p = metadata->scope.scopedParametersHead; p != NULL; ++numParameters, p = sltGetNodeMetadata(p)->parameter.scopedParameterNext);
+
+ // next, count the variables
+ size_t numVariables = 0;
+ for (SLTNode *v = metadata->scope.scopedVariablesHead; v != NULL; ++numVariables, v = sltGetNodeMetadata(v)->variable.scopedVariableNext);
+
+ metadata->function.address = generatorNextInstruction(generator);
+
+ SVMStackOffset workingStackOffset = 1 + numParameters + numVariables;
+ if (node->functionDefinitionBody != NULL) {
+ generator_assert(node->functionDefinitionBody->type == SLTNodeTypeSequence);
+ for (SLTNode *n = node->functionDefinitionBody; n != NULL; n = n->sequenceNext) {
+ generateStatementInstructions(generator, n->sequenceNode, workingStackOffset);
+ }
+ }
+
+ // fallback return
+ generatorAddInstruction(generator, SVMOpcodePOPJUMP);
+}
+
+static size_t generateModuleInstructions(VMGeneratorOutputScope *generator, SLTNode *node) {
+ generator_assert(node != NULL && node->type == SLTNodeTypeModule);
+
+ if (node->moduleStatementsAndDefinitions != NULL) {
+ SVMPointer start = generatorAddInstruction(generator, SVMOpcodeJUMP, 999);
+
+ generator_assert(node->moduleStatementsAndDefinitions->type == SLTNodeTypeSequence);
+
+ // do functions first...
+ for (SLTNode *n = node->moduleStatementsAndDefinitions; n != NULL; n = n->sequenceNext) {
+ if (n->sequenceNode->type == SLTNodeTypeFunctionDefinition) {
+ generateFunctionDefinitionInstructions(generator, n->sequenceNode);
+ }
+ }
+
+ // Patch to jump to the start...
+ SVMOperand address = { .pointerLiteral = generatorNextInstruction(generator) };
+ generatorPatchOperand(generator, start, 0, address);
+
+ // then do variables
+ for (SLTNode *n = node->moduleStatementsAndDefinitions; n != NULL; n = n->sequenceNext) {
+ switch (n->sequenceNode->type) {
+ case SLTNodeTypeFunctionDefinition:
+ // Do nothing...
+ break;
+
+ case SLTNodeTypeVariableDefinition:
+ generateStatementInstructions(generator, n->sequenceNode, 0);
+ break;
+
+ default:
+ //generator_assert_msg(false, "could not define %s", sltNodeTypeToString(n->sequenceNode->type));
+ break;
+ }
+ }
+
+ // statements
+ for (SLTNode *n = node->moduleStatementsAndDefinitions; n != NULL; n = n->sequenceNext) {
+ switch (n->sequenceNode->type) {
+ case SLTNodeTypeVariableDefinition:
+ case SLTNodeTypeTypeDefinition:
+ case SLTNodeTypeFunctionDefinition:
+ // Do nothing...
+ break;
+
+ default:
+ generateStatementInstructions(generator, n->sequenceNode, 0);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+static void patchFunctionCalls(SLTNode *node, void *userParameter) {
+ VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
+ VMNodeMetadata *metadata = sltGetNodeMetadata(node);
+
+ if (node->type == SLTNodeTypeFunctionCall) {
+ if (metadata->functionCall.native == false) {
+ generator_assert_msg(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode->type == SLTNodeTypeFunctionDefinition, "%s", sltNodeToString(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode));
+ SVMOperand operand = { .pointerLiteral = sltGetNodeMetadata(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode)->function.address };
+ generatorPatchOperand(visitor->generator, metadata->functionCall.instruction, 0, operand);
+ }
+ }
+}
+
+
+
+SVMModule *slcGenerateVMInstructions(SLTNode *moduleNode) {
+ VMGeneratorOutputScope *generator = generatorCreate();
+
+ VMGeneratorVisitor visitor;
+
+ sltTreeIterate(moduleNode, addNodeMetadata, NULL, NULL);
+
+ visitor.generator = generator;
+ sltTreeIterate(moduleNode, findStrings, NULL, &visitor);
+
+ visitor.currentScope = NULL;
+ sltTreeIterate(moduleNode, beginScopeNode, endScopeNode, &visitor);
+
+ visitor.generator = generator;
+ sltTreeIterate(moduleNode, scopeDefinitions, NULL, &visitor);
+ sltTreeIterate(moduleNode, resolveDefinitions, resolveDefinitionsNativeFunctions, &visitor);
+ sltTreeIterate(moduleNode, indexDefinitions, NULL, &visitor);
+
+ sltTreeIterate(moduleNode, scopeIterationBreaks, NULL, &visitor);
+
+ /*do {
+ visitor.typeUnresolved = false;
+ visitor.typeChanged = false;
+ sltTreeIterate(moduleNode, resolveTypes, NULL, &visitor);
+ } while (visitor.typeUnresolved && visitor.typeChanged);*/
+
+ generateModuleInstructions(generator, moduleNode);
+
+ visitor.generator = generator;
+ sltTreeIterate(moduleNode, patchFunctionCalls, NULL, &visitor);
+
+
+ SVMModule *module = generatorFinalize(generator);
+
+
+ /*for (size_t i = 0; i < generator->nextInstructionIdx; ++i) {
+ SVMOpcode opcode = generator->instructions[i].instruction.opcode;
+ switch (opcodeOperandCount(opcode)) {
+ case 0:
+ default:
+ printf("%u : %s\n", i, svmOpcodeToString(opcode));
+ break;
+
+ case 1:
+ printf("%u : %s %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset);
+ break;
+
+ case 2:
+ printf("%u : %s %d %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset, generator->instructions[i].instruction.p1.stackOffset);
+ break;
+
+ case 3:
+ printf("%u : %s %d %d %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset, generator->instructions[i].instruction.p1.stackOffset, generator->instructions[i].instruction.p2.stackOffset);
+ break;
+ }
+ }*/
+
+ //fix references...
+
+ return module;
+}