diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index f4fc23b..672bedf 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -3,6 +3,7 @@ #include "SolsScope.h" #include +#include #include "../parser/SolsNode.h" #include "../include/estr.h" @@ -11,6 +12,9 @@ // FIXME show multiple lines for the error char* createCodegenError(SolsNode* node, char* what) { + if (node->line.content == NULL) { + return what; + } Estr err = CREATE_ESTR(ESC_BOLD ESC_RED_FG "error: " ESC_RESET ESC_BOLD); APPEND_ESTR(err, what); APPEND_ESTR(err, "\n" ESC_RESET); @@ -22,11 +26,7 @@ char* createCodegenError(SolsNode* node, char* what) { APPEND_ESTR(err, line_buf); APPEND_ESTR(err, "\n\n"); - if (node->line.content == NULL) { - APPEND_ESTR(err, "(null line)"); - } else { - APPEND_ESTR(err, node->line.content); - } + APPEND_ESTR(err, node->line.content); APPEND_ESTR(err, "\n"); return err.str; @@ -684,13 +684,54 @@ static inline ResultType(GroundProgram, charptr) generateIfNode(SolsNode* node, return Success(GroundProgram, charptr, gp); } +ResultType(GroundProgram, charptr) generateLambdaNode(SolsNode* node, SolsScope* scope) { + GroundProgram gp = groundCreateProgram(); + + // Generate function signature + GroundInstruction signature = groundCreateInstruction(FUN); + char* lambdaId = malloc(sizeof(char) * 64); + snprintf(lambdaId, 64, "__SOLS_LAMBDA_%zu", scope->tmpCounter++); + + groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, lambdaId)); + ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType); + if (arg.error) { + return Error(GroundProgram, charptr, arg.as.error); + } + groundAddReferenceToInstruction(&signature, arg.as.success); + for (size_t i = 0; i < node->as.type.children.count; i++) { + // Add type + ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(&node->as.type.children.at[i].type); + if (arg.error) { + return Error(GroundProgram, charptr, arg.as.error); + } + groundAddReferenceToInstruction(&signature, arg.as.success); + + // Add arg name + groundAddReferenceToInstruction(&signature, groundCreateReference(DIRREF, node->as.type.children.at[i].name)); + } + + groundAddInstructionToProgram(&gp, signature); + + // Generate children and add then to this program + ResultType(GroundProgram, charptr) bodyCode = generateCode(&node->children.at[0], scope); + if (bodyCode.error) return bodyCode; + for (size_t i = 0; i < bodyCode.as.success.size; i++) { + groundAddInstructionToProgram(&gp, bodyCode.as.success.instructions[i]); + } + + // End the function + groundAddInstructionToProgram(&gp, groundCreateInstruction(ENDFUN)); + + return Success(GroundProgram, charptr, gp); +} + ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) { GroundProgram program = groundCreateProgram(); SolsScope backupScope = {NULL, 0}; - if (node->type != SNT_IF && node->type != SNT_WHILE) { + if (node->type != SNT_IF && node->type != SNT_WHILE && node->type != SNT_LAMBDA) { if (node->type == SNT_CODE_BLOCK) { backupScope = *scope; SolsScope newScope = copySolsScope(scope); @@ -730,6 +771,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope case SNT_CODE_BLOCK: generate(CodeBlock); case SNT_IF: generate(If); case SNT_WHILE: generate(While); + case SNT_LAMBDA: generate(Lambda); } return Success(GroundProgram, charptr, program); } diff --git a/src/lexer/SolsType.c b/src/lexer/SolsType.c index a7eb23e..e77fb36 100644 --- a/src/lexer/SolsType.c +++ b/src/lexer/SolsType.c @@ -2,6 +2,7 @@ #include "lexer.h" #include "../include/error.h" #include "../include/estr.h" +#include #include ResultType(SolsType, charptr) createSolsType(SolsTypeType in) { @@ -142,3 +143,34 @@ bool compareTypes(SolsType* left, SolsType* right) { default: return true; } } + +ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type) { + 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: { + // FIXME Do this later + return Error(GroundArg, charptr, "FIXME"); + } + } + return Error(GroundArg, charptr, "How did we get here?"); +} diff --git a/src/lexer/SolsType.h b/src/lexer/SolsType.h index 0d1a1e3..0194c0d 100644 --- a/src/lexer/SolsType.h +++ b/src/lexer/SolsType.h @@ -2,6 +2,7 @@ #define SOLSTYPE_H #include +#include #include "../include/error.h" #include "../include/nothing.h" @@ -90,6 +91,11 @@ ResultType(Nothing, charptr) addChildToSolsType(SolsType* type, SolsType child, // Makes a deep copy of a SolsType. ResultType(SolsType, charptr) copySolsType(SolsType* type); +Result(GroundArg, charptr); + +// Represents a SolsType as a GroundArg (in typeref form) +ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type); + // Frees a SolsType void freeSolsType(SolsType* type); diff --git a/src/main.c b/src/main.c index 3717f8d..473fed7 100644 --- a/src/main.c +++ b/src/main.c @@ -46,7 +46,20 @@ int main(int argc, char** argv) { printf("Usage: %s [file]\n", argv[0]); exit(1); } - char* fileContents = getFileContents(argv[1]); + + char* fileContents = NULL; + bool printProgram = false; + + if (strcmp(argv[1], "-p") == 0) { + if (argc < 3) { + printf("Usage: %s -p [file]\n", argv[0]); + exit(1); + } + printProgram = true; + fileContents = getFileContents(argv[2]); + } else { + fileContents = getFileContents(argv[1]); + } // Lex file ResultType(SolsLexer, charptr) lexer = createLexer(fileContents); @@ -84,6 +97,11 @@ int main(int argc, char** argv) { exit(1); } + if (printProgram) { + groundPrintProgram(&codegen.as.success); + exit(0); + } + // Run program on GroundVM GroundValue retval = groundRunProgram(&codegen.as.success); if (retval.type == INT) {