diff --git a/CMakeLists.txt b/CMakeLists.txt index 435e70d..984d814 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,10 +40,14 @@ add_executable( lib/dropt/dropt_handlers.c # Source src/ast.h + src/compiler.h + src/parser.h src/stack.h src/ast.c - src/stack.c src/compiler.c + src/parser.c + src/stack.c + src/main.c # Generated code ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS} diff --git a/example.w b/example.w new file mode 100644 index 0000000..2adb74e --- /dev/null +++ b/example.w @@ -0,0 +1,41 @@ +struct YourStruct +{ + yourInt: int; +} + +struct MyStruct +{ + myInt: int; + myBool: bool; + yourStructReference: Reference; + yourStruct: YourStruct; + + Increment(): void + { + myInt = myInt + 1; + } + + static MyFunction(input: int): int + { + return input * 2; + } +} + +struct Program +{ + static Main(): int + { + myStruct: MyStruct; + myReference: Reference; + myInt: int; + + myReference = alloc MyStruct; + + myInt = MyStruct.MyFunction(2); + + myStruct.myInt = myInt; + myStruct.Increment(); + + return myStruct.myInt; + } +} diff --git a/generators/wraith.y b/generators/wraith.y index bdb87db..bde907e 100644 --- a/generators/wraith.y +++ b/generators/wraith.y @@ -7,7 +7,7 @@ #include "../src/ast.h" #include "../src/stack.h" -void yyerror(FILE *fp, Stack *stack, char *s) +void yyerror(FILE *fp, Stack *stack, Node **pRootNode, char *s) { fprintf (stderr, "%s\n", s); } @@ -15,8 +15,6 @@ void yyerror(FILE *fp, Stack *stack, char *s) extern char *yytext; extern int yylex (void); extern FILE *yyin; - -extern Node *rootNode; %} %define api.value.type {struct Node*} @@ -62,7 +60,7 @@ extern Node *rootNode; %token COMMENT %token NEWLINE -%parse-param { FILE* fp } { Stack *stack } +%parse-param { FILE* fp } { Stack *stack } { Node **pRootNode } %define parse.error verbose @@ -82,7 +80,7 @@ Program : TopLevelDeclarations PopStackFrame(stack); - rootNode = declarationSequence; + *pRootNode = declarationSequence; } BaseType : VOID diff --git a/src/compiler.c b/src/compiler.c index 48403fe..53168d8 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -13,14 +13,7 @@ #include #include -#include "y.tab.h" #include "ast.h" -#include "stack.h" -#include "../lib/dropt/dropt.h" - -extern FILE *yyin; -Stack *stack; -Node *rootNode; typedef struct LocalVariable { @@ -820,26 +813,17 @@ static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *node) } } -static int Build(char *inputFilename, uint32_t optimizationLevel) +int Build(Node *node, uint32_t optimizationLevel) { scope = CreateScope(); structTypeDeclarations = NULL; structTypeDeclarationCount = 0; - stack = CreateStack(); - - FILE *fp = fopen(inputFilename, "r"); - yyin = fp; - yyparse(fp, stack); - fclose(fp); - - PrintTree(rootNode, 0); - LLVMModuleRef module = LLVMModuleCreateWithName("my_module"); LLVMContextRef context = LLVMGetGlobalContext(); - Compile(module, context, rootNode); + Compile(module, context, node); /* add main call */ LLVMBuilderRef builder = LLVMCreateBuilder(); @@ -886,11 +870,6 @@ static int Build(char *inputFilename, uint32_t optimizationLevel) LLVMPassManagerRef passManager = LLVMCreatePassManager(); - // LLVMAddInstructionCombiningPass(passManager); - // LLVMAddCFGSimplificationPass(passManager); - // LLVMAddReassociatePass(passManager); - // LLVMAddPromoteMemoryToRegisterPass(passManager); - LLVMPassManagerBuilderRef passManagerBuilder = LLVMPassManagerBuilderCreate(); LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, optimizationLevel); LLVMPassManagerBuilderPopulateModulePassManager(passManagerBuilder, passManager); @@ -931,61 +910,3 @@ static int Build(char *inputFilename, uint32_t optimizationLevel) return EXIT_SUCCESS; } - -int main(int argc, char *argv[]) -{ - dropt_bool showHelp; - uint32_t optimizationLevel = 0; - char *inputFilename; - extern int yydebug; - int exitCode = EXIT_SUCCESS; - - dropt_option options[] = { - { 'h', "help", "Shows help.", NULL, dropt_handle_bool, &showHelp, dropt_attr_halt }, - { 'O', "optimize", "Sets optimization level of the output IR. Must be a value between 0 and 3.", "number", dropt_handle_uint, &optimizationLevel }, - { 0 } /* Required sentinel value. */ - }; - - dropt_context *droptContext = dropt_new_context(options); - - if (droptContext == NULL) - { - exitCode = EXIT_FAILURE; - } - else if (argc == 0) - { - printf("Must supply an input file."); - exitCode = EXIT_FAILURE; - } - else - { - char** rest = dropt_parse(droptContext, -1, &argv[1]); - if (dropt_get_error(droptContext) != dropt_error_none) - { - fprintf(stderr, "wraith: %s\n", dropt_get_error_message(droptContext)); - exitCode = EXIT_FAILURE; - } - else if (showHelp) - { - printf("Usage: wraith [options] [--] [input_file]\n\n" - "Options:\n"); - dropt_print_help(stdout, droptContext, NULL); - } - else - { - yydebug = 1; /* FIXME: make this an option */ - inputFilename = *rest; - if (inputFilename == NULL) - { - fprintf(stderr, "ERROR: Must provide an input file.\n"); - exitCode = EXIT_FAILURE; - } - else - { - exitCode = Build(inputFilename, optimizationLevel); - } - } - } - - return exitCode; -} diff --git a/src/compiler.h b/src/compiler.h new file mode 100644 index 0000000..216d2c5 --- /dev/null +++ b/src/compiler.h @@ -0,0 +1,8 @@ +#ifndef WRAITH_COMPILER_H +#define WRAITH_COMPILER_H + +#include "ast.h" + +int Build(Node *node, uint32_t optimizationLevel); + +#endif /* WRAITH_COMPILER_H */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..ff231a1 --- /dev/null +++ b/src/main.c @@ -0,0 +1,74 @@ +#include +#include "../lib/dropt/dropt.h" + +#include "parser.h" +#include "compiler.h" + +int main(int argc, char *argv[]) +{ + dropt_bool showHelp = 0; + dropt_bool parseVerbose = 0; + uint32_t optimizationLevel = 0; + char *inputFilename; + int exitCode = EXIT_SUCCESS; + + dropt_option options[] = { + { 'h', "help", "Shows help.", NULL, dropt_handle_bool, &showHelp, dropt_attr_halt }, + { 'v', "parse-verbose", "Shows verbose parser output.", NULL, dropt_handle_bool, &parseVerbose }, + { 'O', "optimize", "Sets optimization level of the output IR. Must be a value between 0 and 3.", "number", dropt_handle_uint, &optimizationLevel }, + { 0 } /* Required sentinel value. */ + }; + + dropt_context *droptContext = dropt_new_context(options); + + if (droptContext == NULL) + { + exitCode = EXIT_FAILURE; + } + else if (argc == 0) + { + printf("Must supply an input file."); + exitCode = EXIT_FAILURE; + } + else + { + char** rest = dropt_parse(droptContext, -1, &argv[1]); + if (dropt_get_error(droptContext) != dropt_error_none) + { + fprintf(stderr, "wraith: %s\n", dropt_get_error_message(droptContext)); + exitCode = EXIT_FAILURE; + } + else if (showHelp) + { + printf("Usage: wraith [options] [--] [input_file]\n\n" + "Options:\n"); + dropt_print_help(stdout, droptContext, NULL); + } + else + { + /* TODO: free AST after compilation */ + inputFilename = *rest; + + if (inputFilename == NULL) + { + fprintf(stderr, "ERROR: Must provide an input file.\n"); + exitCode = EXIT_FAILURE; + } + else + { + Node *rootNode; + if (Parse(inputFilename, &rootNode, parseVerbose) != 0) + { + fprintf(stderr, "Parser error.\n"); + exitCode = EXIT_FAILURE; + } + else + { + exitCode = Build(rootNode, optimizationLevel); + } + } + } + } + + return exitCode; +} diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..69d9603 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,41 @@ +#include + +#include "y.tab.h" +#include "ast.h" +#include "stack.h" + +extern FILE *yyin; +extern int yydebug; + +int Parse(char *inputFilename, Node **pRootNode, uint8_t parseVerbose) +{ + int result; + Stack *stack = CreateStack(); + yydebug = parseVerbose; + + FILE *fp = fopen(inputFilename, "r"); + yyin = fp; + result = yyparse(fp, stack, pRootNode); + fclose(fp); + + /* TODO: free stack */ + /* TODO: free AST on error */ + + if (result == 0) + { + if (parseVerbose) + { + PrintTree(*pRootNode, 0); + } + } + else if (result == 1) + { + fprintf(stderr, "Syntax error.\n"); + } + else if (result == 2) + { + fprintf(stderr, "Out of memory.\n"); + } + + return result; +} diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 0000000..ba3f6e7 --- /dev/null +++ b/src/parser.h @@ -0,0 +1,8 @@ +#ifndef WRAITH_PARSER_H +#define WRAITH_PARSER_H + +#include "ast.h" + +int Parse(char *inputFilename, Node **pNode, uint8_t parseVerbose); + +#endif /* WRAITH_PARSER_H */