Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b2aa23715 | |||
| 668f13d176 |
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "SolsScope.h"
|
||||
|
||||
#include <groundvm.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
@@ -266,21 +265,24 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
||||
}
|
||||
case SNT_LITERAL: {
|
||||
switch (node->as.literal.type) {
|
||||
case SLT_INT: {
|
||||
case STT_INT: {
|
||||
return Success(SolsType, charptr, {STT_INT});
|
||||
}
|
||||
case SLT_DOUBLE: {
|
||||
case STT_DOUBLE: {
|
||||
return Success(SolsType, charptr, {STT_DOUBLE});
|
||||
}
|
||||
case SLT_STRING: {
|
||||
case STT_STRING: {
|
||||
return Success(SolsType, charptr, {STT_STRING});
|
||||
}
|
||||
case SLT_BOOL: {
|
||||
case STT_BOOL: {
|
||||
return Success(SolsType, charptr, {STT_BOOL});
|
||||
}
|
||||
case SLT_CHAR: {
|
||||
case STT_CHAR: {
|
||||
return Success(SolsType, charptr, {STT_CHAR});
|
||||
}
|
||||
default: {
|
||||
return Error(SolsType, charptr, "Cannot handle literal of specified type");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -397,11 +399,6 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
||||
Estr typeName = CREATE_ESTR(node->children.at[0].as.idName);
|
||||
APPEND_ESTR(typeName, "_SOLS_GENERIC_");
|
||||
for (size_t i = 0; i < node->children.count - 1; i++) {
|
||||
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->children.at[i + 1].as.type, scope);
|
||||
if (arg.error) {
|
||||
return Error(SolsType, charptr, arg.as.error);
|
||||
}
|
||||
APPEND_ESTR(typeName, arg.as.success.value.refName);
|
||||
APPEND_ESTR(typeName, "_");
|
||||
}
|
||||
SolsVariable* variable = findSolsVariable(scope, typeName.str);
|
||||
@@ -554,29 +551,16 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
||||
return Error(SolsType, charptr, "Not yet implemented");
|
||||
}
|
||||
|
||||
SolsVMRegister assignSlot(SolsLiteral literal, SolsScope* scope) {}
|
||||
SolsVMRegister reserveSlot(SolsScope* scope) {}
|
||||
|
||||
/*
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateLiteralNode(SolsNode* node, SolsScope* scope) {
|
||||
// We don't even need to do anything lmao
|
||||
return Success(GroundProgram, charptr, groundCreateProgram());
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node, SolsScope* scope) {
|
||||
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++) {
|
||||
// Validate arg
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[i], scope);
|
||||
if (type.error) {
|
||||
return Error(GroundProgram, charptr, type.as.error);
|
||||
}
|
||||
groundAddReferenceToInstruction(&inst, node->children.at[i].accessArg);
|
||||
}
|
||||
GroundProgram program = groundCreateProgram();
|
||||
groundAddInstructionToProgram(&program, inst);
|
||||
return Success(GroundProgram, charptr, program);
|
||||
}
|
||||
|
||||
static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node, SolsScope* scope) {
|
||||
if (node->children.count < 2) {
|
||||
return Error(GroundProgram, charptr, "set requires arguments");
|
||||
@@ -2298,9 +2282,34 @@ ResultType(GroundProgram, charptr) generateSizeOfNode(SolsNode* node, SolsScope*
|
||||
return Success(GroundProgram, charptr, gp);
|
||||
}
|
||||
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||
*/
|
||||
|
||||
GroundProgram program = groundCreateProgram();
|
||||
static inline ResultType(SolsVMInstructionList, charptr) generatePutsNode(SolsNode* node, SolsScope* scope) {
|
||||
if (node->children.count < 1) {
|
||||
return Error(SolsVMInstructionList, charptr, "puts requires arguments");
|
||||
}
|
||||
SolsVMInstruction inst = createInstruction();
|
||||
inst.inst = SVM_IT_PUTS;
|
||||
SolsVMInstructionList program = createInstList();
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
// Validate arg
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[i], scope);
|
||||
if (type.error) {
|
||||
return Error(SolsVMInstructionList, charptr, type.as.error);
|
||||
}
|
||||
addArgToInstruction(&inst, (SolsVMInstructionArg) {
|
||||
.type = SVM_AT_REGISTER,
|
||||
.as.reg = 0
|
||||
});
|
||||
addInstToInstList(&program, inst);
|
||||
}
|
||||
return Success(SolsVMInstructionList, charptr, program);
|
||||
}
|
||||
|
||||
|
||||
ResultType(SolsVMInstructionList, charptr) generateCode(SolsNode* node, SolsScope* scope) {
|
||||
|
||||
SolsVMInstructionList program;
|
||||
|
||||
SolsScope backupScope = {NULL, 0};
|
||||
|
||||
@@ -2316,12 +2325,12 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
||||
if (node->type == SNT_OP_SET && i == 0) {
|
||||
continue; // Don't evaluate the left of set, just the right
|
||||
}
|
||||
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i], scope);
|
||||
ResultType(SolsVMInstructionList, charptr) generated = generateCode(&node->children.at[i], scope);
|
||||
if (generated.error) {
|
||||
return Error(GroundProgram, charptr, createCodegenError(&node->children.at[i], generated.as.error));
|
||||
return Error(SolsVMInstructionList, charptr, createCodegenError(&node->children.at[i], generated.as.error));
|
||||
}
|
||||
for (size_t j = 0; j < generated.as.success.size; j++) {
|
||||
groundAddInstructionToProgram(&program, generated.as.success.instructions[j]);
|
||||
addInstToInstList(&program, generated.as.success.instructions[j]);
|
||||
}
|
||||
}
|
||||
if (node->type == SNT_CODE_BLOCK) {
|
||||
@@ -2333,6 +2342,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
||||
// Now generate code for this node
|
||||
switch (node->type) {
|
||||
case SNT_PUTS: generate(Puts);
|
||||
/*
|
||||
case SNT_LITERAL: generate(Literal);
|
||||
case SNT_OP_SET: generate(Set);
|
||||
case SNT_OP_ADD: generate(Add);
|
||||
@@ -2363,6 +2373,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
||||
case SNT_GENERIC_INIT: generate(GenericInit);
|
||||
case SNT_AS: generate(As);
|
||||
case SNT_SIZE_OF: generate(SizeOf);
|
||||
*/
|
||||
}
|
||||
return Success(GroundProgram, charptr, program);
|
||||
return Success(SolsVMInstructionList, charptr, program);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
#ifndef CODEGEN_H
|
||||
#define CODEGEN_H
|
||||
|
||||
#include <groundvm.h>
|
||||
|
||||
#include "SolsScope.h"
|
||||
|
||||
#include "../parser/SolsNode.h"
|
||||
#include "../vm/vm.h"
|
||||
|
||||
Result(GroundProgram, charptr);
|
||||
Result(SolsVMInstructionList, charptr);
|
||||
|
||||
// Generates a GroundProgram (from the Ground VM header) from
|
||||
// a provided SolsNode.
|
||||
// a provided SolsNode.
|
||||
// Returns:
|
||||
// Success: Generated GroundProgram
|
||||
// Failure: charptr detailing what happened
|
||||
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope);
|
||||
ResultType(SolsVMInstructionList, charptr) generateCode(SolsNode* node, SolsScope* scope);
|
||||
|
||||
// Gets the type of a node generated by the parser for the type checker.
|
||||
ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope);
|
||||
|
||||
// Macro to help with code generation (and soon error handling)
|
||||
#define generate(nodetype) {\
|
||||
ResultType(GroundProgram, charptr) __result = generate##nodetype##Node(node, scope);\
|
||||
ResultType(SolsVMInstructionList, charptr) __result = generate##nodetype##Node(node, scope);\
|
||||
if (__result.error) {\
|
||||
return Error(GroundProgram, charptr, __result.as.error);\
|
||||
return Error(SolsVMInstructionList, charptr, __result.as.error);\
|
||||
}\
|
||||
for (size_t i = 0; i < __result.as.success.size; i++) {\
|
||||
groundAddInstructionToProgram(&program, __result.as.success.instructions[i]);\
|
||||
}\
|
||||
break;\
|
||||
}
|
||||
|
||||
@@ -4,30 +4,30 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...) {
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsTypeType type, ...) {
|
||||
va_list args;
|
||||
va_start(args, type);
|
||||
SolsLiteral literal = {
|
||||
.type = type
|
||||
};
|
||||
switch (type) {
|
||||
case SLT_INT: {
|
||||
case STT_INT: {
|
||||
literal.as.intv = va_arg(args, int64_t);
|
||||
break;
|
||||
}
|
||||
case SLT_DOUBLE: {
|
||||
case STT_DOUBLE: {
|
||||
literal.as.doublev = va_arg(args, double);
|
||||
break;
|
||||
}
|
||||
case SLT_BOOL: {
|
||||
case STT_BOOL: {
|
||||
literal.as.boolv = (bool) va_arg(args, int);
|
||||
break;
|
||||
}
|
||||
case SLT_CHAR: {
|
||||
case STT_CHAR: {
|
||||
literal.as.charv = (char) va_arg(args, int);
|
||||
break;
|
||||
}
|
||||
case SLT_STRING: {
|
||||
case STT_STRING: {
|
||||
char* input = va_arg(args, char*);
|
||||
if (input == NULL) {
|
||||
va_end(args);
|
||||
@@ -41,38 +41,44 @@ ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...) {
|
||||
strcpy(literal.as.stringv, input);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return Error(SolsLiteral, charptr, "Cannot create literal of specified type");
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
return Success(SolsLiteral, charptr, literal);
|
||||
}
|
||||
|
||||
void freeSolsLiteral(SolsLiteral* lit) {
|
||||
if (lit->type == SLT_STRING && lit->as.stringv != NULL) {
|
||||
if (lit->type == STT_STRING && lit->as.stringv != NULL) {
|
||||
free(lit->as.stringv);
|
||||
}
|
||||
}
|
||||
|
||||
void printSolsLiteral(SolsLiteral* lit) {
|
||||
switch (lit->type) {
|
||||
case SLT_INT: {
|
||||
case STT_INT: {
|
||||
printf("%" PRId64, lit->as.intv);
|
||||
break;
|
||||
}
|
||||
case SLT_DOUBLE: {
|
||||
case STT_DOUBLE: {
|
||||
printf("%f", lit->as.doublev);
|
||||
break;
|
||||
}
|
||||
case SLT_STRING: {
|
||||
case STT_STRING: {
|
||||
printf("%s", lit->as.stringv);
|
||||
break;
|
||||
}
|
||||
case SLT_BOOL: {
|
||||
case STT_BOOL: {
|
||||
printf(lit->as.boolv ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case SLT_CHAR: {
|
||||
case STT_CHAR: {
|
||||
printf("%c", lit->as.charv);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "SolsType.h"
|
||||
|
||||
#include "../include/error.h"
|
||||
#include "../include/nothing.h"
|
||||
|
||||
@@ -16,7 +18,7 @@ typedef enum SolsLiteralType {
|
||||
// Stores literal values which will be added to the Ground code.
|
||||
// Not much explaining needed here.
|
||||
typedef struct SolsLiteral {
|
||||
SolsLiteralType type;
|
||||
SolsTypeType type;
|
||||
union {
|
||||
int64_t intv;
|
||||
char* stringv;
|
||||
@@ -38,7 +40,7 @@ Result(SolsLiteral, charptr);
|
||||
// An error will only be returned if there is an issue copying a provided char*.
|
||||
// There is no way to detect incorrectly provided types, so ensure that the right type
|
||||
// is provided!!!!
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...);
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsTypeType type, ...);
|
||||
|
||||
// Frees a SolsLiteral. Primarily concerned with freeing .as.stringv
|
||||
void freeSolsLiteral(SolsLiteral* lit);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "SolsType.h"
|
||||
#include "../include/error.h"
|
||||
#include "../include/estr.h"
|
||||
#include <groundvm.h>
|
||||
#include <string.h>
|
||||
|
||||
ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
|
||||
@@ -250,52 +249,6 @@ bool compareTypes(SolsType* left, SolsType* right) {
|
||||
}
|
||||
}
|
||||
|
||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type, struct SolsScope* scope) {
|
||||
switch (type->type) {
|
||||
case STT_INT: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "int"));
|
||||
}
|
||||
case STT_DOUBLE: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "double"));
|
||||
}
|
||||
case STT_STRING: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "string"));
|
||||
}
|
||||
case STT_BOOL: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "bool"));
|
||||
}
|
||||
case STT_CHAR: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "char"));
|
||||
}
|
||||
case STT_FUN: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "function"));
|
||||
}
|
||||
case STT_TEMPLATE: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "struct"));
|
||||
}
|
||||
case STT_OBJECT: {
|
||||
if (!type->needsGroundStruct) {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, type->identifierType));
|
||||
} else {
|
||||
// FIXME do this later
|
||||
return Error(GroundArg, charptr, "Anonymous structs are not supported yet");
|
||||
}
|
||||
}
|
||||
case STT_UNKNOWN: {
|
||||
if (!type->needsGroundStruct) {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, type->identifierType));
|
||||
} else {
|
||||
// FIXME do this later
|
||||
return Error(GroundArg, charptr, "Anonymous structs are not supported yet");
|
||||
}
|
||||
}
|
||||
case STT_NONE: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "none"));
|
||||
}
|
||||
}
|
||||
return Error(GroundArg, charptr, "How did we get here?");
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) findStructMemberType(SolsType* type, char* member) {
|
||||
for (size_t i = 0; i < type->children.count; i++) {
|
||||
if (strcmp(type->children.at[i].name, member) == 0) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define SOLSTYPE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <groundvm.h>
|
||||
|
||||
#include "../include/error.h"
|
||||
#include "../include/nothing.h"
|
||||
@@ -114,13 +113,8 @@ ResultType(Nothing, charptr) addChildToSolsType(SolsType* type, SolsType child,
|
||||
// Makes a deep copy of a SolsType.
|
||||
ResultType(SolsType, charptr) copySolsType(SolsType* type);
|
||||
|
||||
Result(GroundArg, charptr);
|
||||
|
||||
struct SolsScope;
|
||||
|
||||
// Represents a SolsType as a GroundArg (in typeref form)
|
||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type, struct SolsScope* scope);
|
||||
|
||||
// Frees a SolsType
|
||||
void freeSolsType(SolsType* type);
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
tokencopy[strlen(token) - 2] = '\0';
|
||||
|
||||
// Create a literal
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_STRING, tokencopy);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_STRING, tokencopy);
|
||||
// Free our copy of the string, createSolsLiteral creates a copy
|
||||
free(tokencopy);
|
||||
if (literal.error) {
|
||||
@@ -285,7 +285,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
return Error(SolsToken, charptr, "Characters can only hold one character at a time (try using \"this\" for strings?)");
|
||||
}
|
||||
if (token[2] == '\'') {
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_CHAR, token[1]);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_CHAR, token[1]);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -319,7 +319,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
}
|
||||
if (isInt) {
|
||||
int64_t newInt = atoll(token);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_INT, newInt);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_INT, newInt);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -334,7 +334,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
|
||||
if (isDouble) {
|
||||
double newDouble = atof(token);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_DOUBLE, newDouble);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_DOUBLE, newDouble);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -350,7 +350,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
|
||||
// Handle boolean (true/false)
|
||||
if (strcmp(token, "true") == 0) {
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_BOOL, true);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_BOOL, true);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -363,7 +363,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
return Success(SolsToken, charptr, tok);
|
||||
}
|
||||
if (strcmp(token, "false") == 0) {
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_BOOL, false);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_BOOL, false);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
|
||||
15
src/main.c
15
src/main.c
@@ -14,7 +14,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
#include <groundvm.h>
|
||||
|
||||
extern bool groundDisableTypeChecking;
|
||||
|
||||
@@ -66,7 +65,7 @@ Args parseArgs(int argc, char** argv) {
|
||||
return args;
|
||||
}
|
||||
i++;
|
||||
args.outputFile = argv[i];
|
||||
args.outputFile = argv[i];
|
||||
}
|
||||
else if (strcmp("-c", argv[i]) == 0 || strcmp("--compile", argv[i]) == 0) {
|
||||
if (args.action != SA_EXEC) {
|
||||
@@ -81,7 +80,7 @@ Args parseArgs(int argc, char** argv) {
|
||||
return args;
|
||||
}
|
||||
i++;
|
||||
args.outputFile = argv[i];
|
||||
args.outputFile = argv[i];
|
||||
}
|
||||
else {
|
||||
args.inputFile = argv[i];
|
||||
@@ -168,12 +167,16 @@ int main(int argc, char** argv) {
|
||||
};
|
||||
|
||||
// Do codegen on root node
|
||||
ResultType(GroundProgram, charptr) codegen = generateCode(&parser.as.success.output, &scope);
|
||||
ResultType(SolsVMInstructionList, charptr) codegen = generateCode(&parser.as.success.output, &scope);
|
||||
if (codegen.error) {
|
||||
printf("%s\n", codegen.as.error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#warning fix runtime
|
||||
|
||||
/*
|
||||
|
||||
switch (args.action) {
|
||||
case SA_PRINT: {
|
||||
groundPrintProgram(&codegen.as.success);
|
||||
@@ -232,7 +235,7 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Link with ld
|
||||
// Link with ld
|
||||
Estr ldcmd = CREATE_ESTR("ld -o ");
|
||||
APPEND_ESTR(ldcmd, args.outputFile);
|
||||
APPEND_ESTR(ldcmd, " ");
|
||||
@@ -250,5 +253,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define SOLSNODE_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <groundvm.h>
|
||||
|
||||
#include "../include/error.h"
|
||||
|
||||
@@ -52,9 +51,6 @@ typedef struct SolsNode {
|
||||
struct SolsNode* at;
|
||||
} children;
|
||||
LineInfo line;
|
||||
|
||||
// Used by the code generator, unless value is a literal do not use in parser
|
||||
GroundArg accessArg;
|
||||
} SolsNode;
|
||||
|
||||
Result(SolsNode, charptr);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "../include/estr.h"
|
||||
#include "../include/ansii.h"
|
||||
#include "../interactive/interactive.h"
|
||||
#include <groundvm.h>
|
||||
#include <string.h>
|
||||
|
||||
SolsTokenPrecedence getPrecedence(SolsToken *token) {
|
||||
@@ -179,10 +178,7 @@ static inline ResultType(Nothing, charptr) parseIdentifier(SolsParser* parser) {
|
||||
return Error(Nothing, charptr, err.str);
|
||||
}
|
||||
node.as.success.line = peek.as.success.line;
|
||||
node.as.success.accessArg = (GroundArg) {
|
||||
.type = VALREF,
|
||||
.value.refName = peek.as.success.as.idName
|
||||
};
|
||||
#warning Fix identifiers
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
return Success(Nothing, charptr, {});
|
||||
}
|
||||
@@ -901,33 +897,41 @@ static inline ResultType(Nothing, charptr) parseLiteral(SolsParser* parser) {
|
||||
return Error(Nothing, charptr, err.str);
|
||||
}
|
||||
node.as.success.line = peek.as.success.line;
|
||||
/*
|
||||
GroundValue value;
|
||||
switch (peek.as.success.as.literal.type) {
|
||||
case SLT_INT: {
|
||||
case STT_INT: {
|
||||
value = groundCreateValue(INT, peek.as.success.as.literal.as.intv);
|
||||
break;
|
||||
}
|
||||
case SLT_DOUBLE: {
|
||||
case STT_DOUBLE: {
|
||||
value = groundCreateValue(DOUBLE, peek.as.success.as.literal.as.doublev);
|
||||
break;
|
||||
}
|
||||
case SLT_STRING: {
|
||||
case STT_STRING: {
|
||||
value = groundCreateValue(STRING, peek.as.success.as.literal.as.stringv);
|
||||
break;
|
||||
}
|
||||
case SLT_BOOL: {
|
||||
case STT_BOOL: {
|
||||
value = groundCreateValue(BOOL, peek.as.success.as.literal.as.boolv);
|
||||
break;
|
||||
}
|
||||
case SLT_CHAR: {
|
||||
case STT_CHAR: {
|
||||
value = groundCreateValue(CHAR, peek.as.success.as.literal.as.charv);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return Error(Nothing, charptr, "Cannot handle literal of specified type");
|
||||
}
|
||||
}
|
||||
node.as.success.accessArg = (GroundArg) {
|
||||
.type = VALUE,
|
||||
.value.value = value
|
||||
};
|
||||
*/
|
||||
|
||||
#warning Fix literals in new VM
|
||||
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
return Success(Nothing, charptr, {});
|
||||
}
|
||||
@@ -1327,10 +1331,15 @@ static inline ResultType(Nothing, charptr) parseDef(SolsParser* parser) {
|
||||
return Error(Nothing, charptr, nameNode.as.error);
|
||||
}
|
||||
nameNode.as.success.line = nameTok.as.success.line;
|
||||
/*
|
||||
nameNode.as.success.accessArg = (GroundArg) {
|
||||
.type = VALREF,
|
||||
.value.refName = nameTok.as.success.as.idName
|
||||
};
|
||||
*/
|
||||
|
||||
#warning Fix function definitions
|
||||
|
||||
addChildToSolsNode(&node.as.success, nameNode.as.success);
|
||||
|
||||
// Parse type signature
|
||||
@@ -1605,7 +1614,7 @@ static inline ResultType(Nothing, charptr) parseUse(SolsParser* parser) {
|
||||
}
|
||||
node.as.success.as.idName = name.as.success.as.idName;
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
} else if (name.as.success.type == STT_LITERAL && name.as.success.as.literal.type == SLT_STRING) {
|
||||
} else if (name.as.success.type == STT_LITERAL && name.as.success.as.literal.type == STT_STRING) {
|
||||
ResultType(SolsNode, charptr) node = createSolsNode(SNT_LOCAL_USE);
|
||||
if (node.error) {
|
||||
return Error(Nothing, charptr, node.as.error);
|
||||
|
||||
@@ -59,7 +59,7 @@ ResultType(SolsType, charptr) parseType(SolsTokens* in, size_t* index) {
|
||||
freeSolsType(&funType);
|
||||
return retType;
|
||||
}
|
||||
|
||||
|
||||
// Allocate memory for returnType pointer
|
||||
funType.returnType = malloc(sizeof(SolsType));
|
||||
if (funType.returnType == NULL) {
|
||||
@@ -91,7 +91,7 @@ ResultType(SolsType, charptr) parseType(SolsTokens* in, size_t* index) {
|
||||
freeSolsType(&complexType);
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
|
||||
char* fieldName = NULL;
|
||||
if (*index < in->count && in->at[*index].type == STT_IDENTIFIER) {
|
||||
fieldName = in->at[*index].as.idName;
|
||||
@@ -116,7 +116,7 @@ ResultType(SolsType, charptr) parseType(SolsTokens* in, size_t* index) {
|
||||
(*index)++; // skip )
|
||||
return Success(SolsType, charptr, complexType);
|
||||
}
|
||||
|
||||
|
||||
// Handle user-defined types (as identifiers)
|
||||
// For now, let's just create an OBJECT type with identifierType set
|
||||
ResultType(SolsType, charptr) userTypeRes = createSolsType(STT_OBJECT);
|
||||
@@ -143,9 +143,9 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
SolsTokens tokens = tokensres.as.success;
|
||||
|
||||
for (size_t i = 0; i < in->count; ) {
|
||||
if (in->at[i].type == STT_IDENTIFIER &&
|
||||
(strcmp(in->at[i].as.idName, "fun") == 0 ||
|
||||
strcmp(in->at[i].as.idName, "object") == 0 ||
|
||||
if (in->at[i].type == STT_IDENTIFIER &&
|
||||
(strcmp(in->at[i].as.idName, "fun") == 0 ||
|
||||
strcmp(in->at[i].as.idName, "object") == 0 ||
|
||||
strcmp(in->at[i].as.idName, "template") == 0)) {
|
||||
size_t startIndex = i;
|
||||
ResultType(SolsType, charptr) typeRes = parseType(in, &i);
|
||||
@@ -153,13 +153,13 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
// For now, return error
|
||||
return Error(SolsTokens, charptr, typeRes.as.error);
|
||||
}
|
||||
|
||||
|
||||
ResultType(SolsToken, charptr) tokenRes = createSolsToken(STT_TYPE, typeRes.as.success);
|
||||
if (tokenRes.error) {
|
||||
freeSolsType(&typeRes.as.success);
|
||||
return Error(SolsTokens, charptr, tokenRes.as.error);
|
||||
}
|
||||
|
||||
|
||||
// Add line info from original token
|
||||
tokenRes.as.success.line.num = in->at[startIndex].line.num;
|
||||
if (in->at[startIndex].line.content) {
|
||||
@@ -170,7 +170,7 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
} else {
|
||||
tokenRes.as.success.line.content = NULL;
|
||||
}
|
||||
|
||||
|
||||
addTokenToSolsTokens(&tokens, tokenRes.as.success);
|
||||
// SolsToken now owns typeRes.as.success and its buffers.
|
||||
} else {
|
||||
@@ -180,7 +180,7 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
// But 'in' tokens might be freed later.
|
||||
// Actually, we are creating a *new* SolsTokens.
|
||||
// So we should probably copy the token properly.
|
||||
|
||||
|
||||
SolsToken original = in->at[i];
|
||||
SolsToken copy = {0};
|
||||
copy.type = original.type;
|
||||
@@ -202,8 +202,8 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
case STT_LITERAL:
|
||||
// Literals also need deep copy?
|
||||
// SolsLiteral has stringv.
|
||||
if (original.as.literal.type == SLT_STRING) {
|
||||
copy.as.literal.type = SLT_STRING;
|
||||
if (original.as.literal.type == STT_STRING) {
|
||||
copy.as.literal.type = STT_STRING;
|
||||
copy.as.literal.as.stringv = malloc(strlen(original.as.literal.as.stringv) + 1);
|
||||
if (copy.as.literal.as.stringv) strcpy(copy.as.literal.as.stringv, original.as.literal.as.stringv);
|
||||
} else {
|
||||
|
||||
150
src/vm/vm.c
Normal file
150
src/vm/vm.c
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "vm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
[[noreturn]] static void criticalRuntimeError(char* msg) {
|
||||
fprintf(stderr, "SolsVM critical runtime error: %s\n", msg);
|
||||
fprintf(stderr, "If you believe this to be a bug, please report at https://chookspace.com/solstice/solstice\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static SolsVMValue* getRegister(SolsVMRegister reg, SolsVMState* state) {
|
||||
switch (reg) {
|
||||
case SVM_R0: return &state->registers.r0;
|
||||
case SVM_R1: return &state->registers.r1;
|
||||
case SVM_R2: return &state->registers.r2;
|
||||
case SVM_R3: return &state->registers.r3;
|
||||
case SVM_R4: return &state->registers.r4;
|
||||
case SVM_R5: return &state->registers.r5;
|
||||
case SVM_R6: return &state->registers.r6;
|
||||
case SVM_R7: return &state->registers.r7;
|
||||
case SVM_R8: return &state->registers.r8;
|
||||
case SVM_R9: return &state->registers.r9;
|
||||
case SVM_R10: return &state->registers.r10;
|
||||
case SVM_R11: return &state->registers.r11;
|
||||
case SVM_R12: return &state->registers.r12;
|
||||
case SVM_R13: return &state->registers.r13;
|
||||
case SVM_R14: return &state->registers.r14;
|
||||
case SVM_R15: return &state->registers.r15;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t getSizeOf(SolsTypeType type) {
|
||||
switch (type) {
|
||||
case STT_INT:
|
||||
case STT_DOUBLE:
|
||||
case STT_STRING:
|
||||
return 8;
|
||||
case STT_BOOL:
|
||||
case STT_CHAR:
|
||||
return 1;
|
||||
case STT_FUN:
|
||||
return sizeof(SolsVMFunction);
|
||||
case STT_TEMPLATE:
|
||||
return sizeof(SolsVMStruct);
|
||||
case STT_OBJECT:
|
||||
return 0; // Object has custom size, signal with 0
|
||||
case STT_GENERIC:
|
||||
case STT_UNKNOWN:
|
||||
case STT_NONE:
|
||||
criticalRuntimeError("Unresolved type during runtime");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* puts instruction
|
||||
* Args: register, core type
|
||||
* Does: puts something on the console
|
||||
*/
|
||||
|
||||
static inline void inst_puts(SolsVMInstruction* inst, SolsVMState* state) {
|
||||
SolsVMValue reg = *getRegister(inst->args.at[0].as.reg, state);
|
||||
switch (inst->args.at[1].as.type) {
|
||||
case STT_INT: {
|
||||
printf("%" PRId64 "\n", *(int64_t*)reg);
|
||||
break;
|
||||
}
|
||||
case STT_DOUBLE: {
|
||||
printf("%f\n", *(double*)reg);
|
||||
break;
|
||||
}
|
||||
case STT_STRING: {
|
||||
printf("%s\n", *(char**)reg);
|
||||
break;
|
||||
}
|
||||
case STT_CHAR: {
|
||||
printf("%c\n", *(char*)reg);
|
||||
break;
|
||||
}
|
||||
case STT_BOOL: {
|
||||
printf("%s\n", (*(bool*)reg) ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case STT_FUN: {
|
||||
printf("<function>\n");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// FIXME handle structs and objects later
|
||||
printf("<FIXME>\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* store instruction
|
||||
* Stores a literal in a register
|
||||
* Args: register, literal
|
||||
* Does: Stores provided literal in the provided register
|
||||
*/
|
||||
static inline void inst_store(SolsVMInstruction* inst, SolsVMState* state) {
|
||||
SolsVMValue* reg = getRegister(inst->args.at[0].as.reg, state);
|
||||
if (*reg != NULL) free(*reg);
|
||||
*reg = malloc(getSizeOf(inst->args.at[1].as.literal.type));
|
||||
}
|
||||
|
||||
void runSolsVMInstruction(SolsVMInstruction* inst, SolsVMState* state) {
|
||||
switch (inst->inst) {
|
||||
case SVM_IT_PUTS: inst_puts(inst, state); break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inst_put(SolsVMInstruction* inst, SolsVMState* state) {}
|
||||
|
||||
void runSolsVM(SolsVMInstructionList* list) {
|
||||
SolsVMState state = {
|
||||
.registers = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
},
|
||||
.stackSize = 0
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < list->size; i++) {
|
||||
runSolsVMInstruction(&list->instructions[i], &state);
|
||||
}
|
||||
|
||||
// Cleanup - free registers and stack
|
||||
if (state.registers.r0 != NULL) free(state.registers.r0);
|
||||
if (state.registers.r1 != NULL) free(state.registers.r1);
|
||||
if (state.registers.r2 != NULL) free(state.registers.r2);
|
||||
if (state.registers.r3 != NULL) free(state.registers.r3);
|
||||
if (state.registers.r4 != NULL) free(state.registers.r4);
|
||||
if (state.registers.r5 != NULL) free(state.registers.r5);
|
||||
if (state.registers.r6 != NULL) free(state.registers.r6);
|
||||
if (state.registers.r7 != NULL) free(state.registers.r7);
|
||||
if (state.registers.r8 != NULL) free(state.registers.r8);
|
||||
if (state.registers.r9 != NULL) free(state.registers.r9);
|
||||
if (state.registers.r10 != NULL) free(state.registers.r10);
|
||||
if (state.registers.r11 != NULL) free(state.registers.r11);
|
||||
if (state.registers.r12 != NULL) free(state.registers.r12);
|
||||
if (state.registers.r13 != NULL) free(state.registers.r13);
|
||||
if (state.registers.r14 != NULL) free(state.registers.r14);
|
||||
if (state.registers.r15 != NULL) free(state.registers.r15);
|
||||
|
||||
for (size_t i = 0; i < state.stackSize; i++) {
|
||||
if (state.stack[i] != NULL) free(state.stack[i]);
|
||||
}
|
||||
}
|
||||
75
src/vm/vm.h
Normal file
75
src/vm/vm.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef VM_H
|
||||
#define VM_H
|
||||
|
||||
#define SVM_STACK_SIZE 8192
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../lexer/SolsLiteral.h"
|
||||
#include "../lexer/SolsType.h"
|
||||
|
||||
typedef enum SolsVMRegister {
|
||||
SVM_R0, SVM_R1, SVM_R2, SVM_R3, SVM_R4, SVM_R5, SVM_R6, SVM_R7, SVM_R8, SVM_R9, SVM_R10, SVM_R11, SVM_R12, SVM_R13, SVM_R14, SVM_R15
|
||||
} SolsVMRegister;
|
||||
|
||||
typedef void* SolsVMValue;
|
||||
|
||||
typedef struct SolsVMState {
|
||||
struct {
|
||||
SolsVMValue r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
} registers;
|
||||
SolsVMValue stack[SVM_STACK_SIZE];
|
||||
uint32_t stackSize;
|
||||
} SolsVMState;
|
||||
|
||||
typedef enum SolsVMInstructionType {
|
||||
SVM_IT_PUTS
|
||||
} SolsVMInstructionType;
|
||||
|
||||
typedef enum SolsVMInstructionArgType {
|
||||
SVM_AT_LITERAL, SVM_AT_REGISTER, SVM_AT_TYPE
|
||||
} SolsVMInstructionArgType;
|
||||
|
||||
typedef struct SolsVMInstructionArg {
|
||||
SolsVMInstructionArgType type;
|
||||
union {
|
||||
SolsVMRegister reg;
|
||||
SolsLiteral literal;
|
||||
SolsTypeType type;
|
||||
} as;
|
||||
} SolsVMInstructionArg;
|
||||
|
||||
typedef struct SolsVMInstruction {
|
||||
SolsVMInstructionType inst;
|
||||
struct {
|
||||
SolsVMInstructionArg* at;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} args;
|
||||
} SolsVMInstruction;
|
||||
|
||||
SolsVMInstruction createInstruction();
|
||||
void addArgToInstruction(SolsVMInstruction* inst, SolsVMInstructionArg arg);
|
||||
|
||||
typedef struct SolsVMInstructionList {
|
||||
SolsVMInstruction* instructions;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} SolsVMInstructionList;
|
||||
|
||||
SolsVMInstructionList createInstList();
|
||||
void addInstToInstList(SolsVMInstructionList* list, SolsVMInstruction inst);
|
||||
|
||||
typedef struct SolsVMFunction {
|
||||
SolsVMInstructionList list;
|
||||
SolsVMState state;
|
||||
} SolsVMFunction;
|
||||
|
||||
typedef struct SolsVMStruct {
|
||||
int x; // Placeholder
|
||||
} SolsVMStruct;
|
||||
|
||||
void runSolsVM(SolsVMInstructionList* list);
|
||||
|
||||
#endif
|
||||
10
src/vm/vm.md
Normal file
10
src/vm/vm.md
Normal file
@@ -0,0 +1,10 @@
|
||||
VM Architecture
|
||||
|
||||
* Everything is a `void*`, and the Solstice compiler will resolve all types before execution. No type safety is in the VM
|
||||
* 16 registers which all hold a `void*`.
|
||||
* `void*` can hold:
|
||||
* A literal (int64_t, char*, double, bool, char)
|
||||
* A function (stored as SolsVMFunction)
|
||||
* A struct (stored as SolsVMStruct)
|
||||
* An object (multiple fields after each other, each thing has 8 bytes of padding)
|
||||
* Overwritten registers are freed
|
||||
@@ -8,8 +8,6 @@
|
||||
#include "parser/parser.h"
|
||||
#include "codegen/codegen.h"
|
||||
|
||||
#include <groundvm.h>
|
||||
|
||||
|
||||
static char out_buf[65536];
|
||||
static int out_pos = 0;
|
||||
|
||||
Reference in New Issue
Block a user