diff --git a/src/codegen/SolsScope.c b/src/codegen/SolsScope.c index ad696ea..54e81d9 100644 --- a/src/codegen/SolsScope.c +++ b/src/codegen/SolsScope.c @@ -26,7 +26,8 @@ SolsVariable* findSolsVariable(SolsScope* scope, const char* name) { SolsScope copySolsScope(SolsScope* scope) { SolsScope newScope = { .variables = NULL, - .tmpCounter = scope->tmpCounter + .tmpCounter = scope->tmpCounter, + .returnType = scope->returnType }; SolsVariable *var, *tmp; diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index b1a8e26..b51cd33 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -5,7 +5,10 @@ #include #include #include +#include +#include "../lexer/lexer.h" +#include "../parser/parser.h" #include "../parser/SolsNode.h" #include "../include/estr.h" #include "../include/uthash.h" @@ -902,6 +905,76 @@ ResultType(GroundProgram, charptr) generateReturnNode(SolsNode* node, SolsScope* return Success(GroundProgram, charptr, program); } +// For generateUseNode function, implemented in src/main.c +char* getFileContents(const char* filename); + +ResultType(GroundProgram, charptr) generateUseNode(SolsNode* node, SolsScope* scope) { + char* libraryName = node->as.idName; + char* libPath = getenv("SOLSTICE_LIBS"); + if (libPath == NULL) { + libPath = "/usr/lib/solstice"; + } + + Estr filePath = CREATE_ESTR(libPath); + APPEND_ESTR(filePath, "/"); + APPEND_ESTR(filePath, libraryName); + APPEND_ESTR(filePath, ".sols"); + + // Steal the main function for use here + char* file = getFileContents(filePath.str); + if (file == NULL) { + return Error(GroundProgram, charptr, "Couldn't read contents of imported file"); + } + ResultType(SolsLexer, charptr) lexer = createLexer(file); + if (lexer.error) { + printf("While lexing file %s:\n", filePath.str); + printf("Error while creating lexer: %s", lexer.as.error); + exit(1); + } + ResultType(Nothing, charptr) lexed = lex(&lexer.as.success); + if (lexed.error) { + printf("While lexing file %s:\n", filePath.str); + printf("%s\n", lexed.as.error); + exit(1); + } + + // Parse file + ResultType(SolsParser, charptr) parser = createSolsParser(&lexer.as.success.output); + if (parser.error) { + printf("While parsing file %s:\n", filePath.str); + printf("Error while creating parser: %s\n", parser.as.error); + exit(1); + } + ResultType(Nothing, charptr) parsed = parse(&parser.as.success); + if (parsed.error) { + printf("While parsing file %s:\n", filePath.str); + printf("%s\n", parsed.as.error); + exit(1); + } + + SolsScope newScope = { + .variables = NULL, + .tmpCounter = 0, + .returnType = createSolsType(STT_INT).as.success + }; + + // Do codegen on root node + ResultType(GroundProgram, charptr) codegen = generateCode(&parser.as.success.output, &newScope); + if (codegen.error) { + printf("While generating code for file %s:\n", filePath.str); + printf("%s\n", codegen.as.error); + exit(1); + } + + // Insert all the stuff into our scope + SolsVariable *var, *tmp; + HASH_ITER(hh, scope->variables, var, tmp) { + addVariableToScope(&newScope, var->id, var->typeinfo); + } + + return Success(GroundProgram, charptr, codegen.as.success); +} + ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) { GroundProgram program = groundCreateProgram(); @@ -952,6 +1025,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope case SNT_DEF: generate(Def); case SNT_FUNCTION_CALL: generate(FunctionCall); case SNT_RETURN: generate(Return); + case SNT_USE: generate(Use); } return Success(GroundProgram, charptr, program); } diff --git a/src/lexer/SolsToken.h b/src/lexer/SolsToken.h index d3c7466..f87a7fe 100644 --- a/src/lexer/SolsToken.h +++ b/src/lexer/SolsToken.h @@ -10,7 +10,7 @@ #include "SolsLiteral.h" typedef enum SolsTokenType { - STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_DOT, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_ADDTO, STT_OP_SUBTO, STT_OP_MULTO, STT_OP_DIVTO, STT_OP_INCREMENT, STT_OP_DECREMENT, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_LAMBDA, STT_KW_RETURN, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA + STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_DOT, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_ADDTO, STT_OP_SUBTO, STT_OP_MULTO, STT_OP_DIVTO, STT_OP_INCREMENT, STT_OP_DECREMENT, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_LAMBDA, STT_KW_RETURN, STT_KW_USE, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA } SolsTokenType; typedef char* charptr; diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 908a9d0..d01a002 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -13,6 +13,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = { {"def", STT_KW_DEF}, {"lambda", STT_KW_LAMBDA}, {"return", STT_KW_RETURN}, + {"use", STT_KW_USE}, {"struct", STT_KW_STRUCT}, {"{", STT_OPEN_CURLY}, {"}", STT_CLOSE_CURLY}, diff --git a/src/main.c b/src/main.c index d429284..2f6cdde 100644 --- a/src/main.c +++ b/src/main.c @@ -25,15 +25,13 @@ char* getFileContents(const char* filename) { file = calloc(1, lSize + 1); if (!file) { fclose(fp); - fputs("memory allocation fail when reading file", stderr); - exit(1); + return NULL; } if (1!=fread(file, lSize, 1, fp)) { fclose(fp); free(file); - fputs("couldn't read entire file", stderr); - exit(1); + return NULL; } // we done @@ -62,6 +60,11 @@ int main(int argc, char** argv) { fileContents = getFileContents(argv[1]); } + if (fileContents == NULL) { + printf("Couldn't read that file :(\n"); + exit(1); + } + // Lex file ResultType(SolsLexer, charptr) lexer = createLexer(fileContents); if (lexer.error) { diff --git a/src/parser/SolsNode.h b/src/parser/SolsNode.h index f77a139..b0f8961 100644 --- a/src/parser/SolsNode.h +++ b/src/parser/SolsNode.h @@ -11,7 +11,7 @@ #include "../lexer/SolsToken.h" typedef enum SolsNodeType { - SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_LAMBDA, SNT_FUNCTION_CALL, SNT_RETURN, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT + SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_LAMBDA, SNT_FUNCTION_CALL, SNT_RETURN, SNT_USE, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT } SolsNodeType; struct SolsNode; diff --git a/src/parser/parser.c b/src/parser/parser.c index db1c2a7..3977067 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1556,6 +1556,21 @@ static inline ResultType(Nothing, charptr) parseReturn(SolsParser* parser) { return Success(Nothing, charptr, {}); } +static inline ResultType(Nothing, charptr) parseUse(SolsParser* parser) { + ResultType(SolsToken, Nothing) name = parserConsume(parser); + if (name.error || name.as.success.type != STT_IDENTIFIER) { + return Error(Nothing, charptr, "Expecting identifier after 'use'"); + } + ResultType(SolsNode, charptr) node = createSolsNode(SNT_USE); + if (node.error) { + return Error(Nothing, charptr, node.as.error); + } + node.as.success.as.idName = name.as.success.as.idName; + addChildToSolsNode(parser->currentParent, node.as.success); + + return Success(Nothing, charptr, {}); +} + static inline ResultType(Nothing, charptr) parseOpenParen(SolsParser* parser) { return Error(Nothing, charptr, "WIP"); } @@ -1580,6 +1595,7 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) { case STT_KW_WHILE: PARSER_HANDLE(While); case STT_KW_LAMBDA: PARSER_HANDLE(Lambda); case STT_KW_RETURN: PARSER_HANDLE(Return); + case STT_KW_USE: PARSER_HANDLE(Use); case STT_KW_DEF: PARSER_HANDLE(Def); case STT_OP_SET: PARSER_HANDLE(Set); case STT_OP_ADD: PARSER_HANDLE(Add);