// The M Programming Language // It is a subset of C, and named after it as a single letter and from the // first letter of my OS project Project "Metal". // This compiler directly produces x86 machine code. // It boths compiles the OS, and (will be) part of it in an integrated manner. // This compiler will be the JIT shell of the userspace (and kernelspace), and // hot reloading will solely be supported through this language. // This is an extremely simple stack-machine one-pass compiler. // This will produce binary results that are slower than gcc or other production // compilers. However, it remains reasonable, which is the goal for a learning // compiler and OS development. // AST node system is not used so that the compiler can be up and running as // soon as possible. #include #include #include #include #include #include #include "lex.h" #include "sv.h" #include "parser.h" int main() { struct string_pool sp; sp_init(&sp); struct token* tokens = malloc(1024*1024); struct string_view src_file = backend_stream_init_src("code.m"); DEBUG("File, size: %d, content:\n%s", src_file.len, src_file.buf); struct lex_config lc; lc.src = src_file.buf; lc.size = src_file.len; lc.sp = &sp; lc.pos = 0; int index = 0; DEBUG("---TOKENIZER START---\n"); do { tokens[index] = lex_next(&lc); index++; } while(tokens[index - 1].type != T_EOF); DEBUG("---TOKENIZER END---\n"); DEBUG("Tokenizer ran %d times!\n", index); for(int i = 0; i < index; i++) { DEBUG("Token %d: type|%x|content|%.*s.\n", i, tokens[i].type, tokens[i].me.len, tokens[i].me.buf); } backend_stream_init_dst("code.o"); DEBUG("---PARSER START---\n"); struct parser_config pc; pc.tokens = tokens; pc.size = index; pc.pos = 0; parser_parse(&pc); DEBUG("---PARSER END---\n"); if(pc.state == PARSER_GRACEFUL) { printf("\nBinary compiled!\n"); exit(0); } else { printf("\nCompilation failed!\n"); exit(1); } return 0; }