diff --git a/liamc/CMakeLists.txt b/liamc/CMakeLists.txt index 69a0267d..c313166b 100644 --- a/liamc/CMakeLists.txt +++ b/liamc/CMakeLists.txt @@ -12,14 +12,13 @@ add_executable(liamc "src/expression.cpp" "src/statement.cpp" "src/lexer.cpp" - "src/parser.cpp" + "src/parser.cpp" "src/liam.cpp" "src/rust_backend/rust_backend.cpp" "src/type_checker.cpp" "src/errors.cpp" "include/liam.h" - "include/generator.h" "include/lexer.h" "include/parser.h" "include/statement.h" @@ -27,7 +26,6 @@ add_executable(liamc "include/rust_backend/rust_backend.h" "include/type_checker.h" "include/compiler.h" - "include/macros.h" "include/errors.h" "include/type_info.h" ) diff --git a/liamc/include/compiler.h b/liamc/include/compiler.h index dcb1799a..38fc76fd 100644 --- a/liamc/include/compiler.h +++ b/liamc/include/compiler.h @@ -5,6 +5,7 @@ #include "type_checker.h" #include "lexer.h" #include "errors.h" +#include "liam.h" #include std::vector lex_parse(std::filesystem::path path) { diff --git a/liamc/include/errors.h b/liamc/include/errors.h index 1c61d687..8e0a333f 100644 --- a/liamc/include/errors.h +++ b/liamc/include/errors.h @@ -2,11 +2,12 @@ #include #include #include +#include "liam.h" struct ErrorReport { std::string file; - int line; - int character; + s32 line; + s32 character; std::string error; }; @@ -16,7 +17,7 @@ struct ErrorReporter { ErrorReporter(); - static void report_error(std::string file, int line, int character, std::string message); + static void report_error(std::string file, s32 line, s32 character, std::string message); static std::vector* all_reports(); static bool has_errors(); }; diff --git a/liamc/include/expression.h b/liamc/include/expression.h index 1ca250af..302af399 100644 --- a/liamc/include/expression.h +++ b/liamc/include/expression.h @@ -1,6 +1,5 @@ #pragma once #include "lexer.h" -#include "liam.h" #include "type_info.h" enum class ExpressionType { diff --git a/liamc/include/generator.h b/liamc/include/generator.h deleted file mode 100644 index 78ba2446..00000000 --- a/liamc/include/generator.h +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once - -#include "liam.h" -#include -#include -#include -#include -#include - -namespace liam { - struct OpCommand { - std::string name; - OpCode op; - size_t arguments; - }; - - static OpCommand operations[] = { - OpCommand{"add", OpCode::ADD, 0}, - OpCommand{"print", OpCode::PRINT, 0}, - OpCommand{"push", OpCode::PUSH, 1}, - OpCommand{"goto", OpCode::GOTO, 1}, - }; - - std::vector extract_words(const char* path) { - auto vec = std::vector(); - - std::ifstream file; - file.open(path); - - std::string word; - while (file >> word) - { - vec.push_back(word); - } - - file.close(); - return vec; - } - - struct Generator - { - std::map labels; - - std::tuple generate(const char* path) { - auto words = extract_words(path); - VM vm{0}; - - int index = 0; - while(index < words.size()) { - auto word = words.at(index); - - if(word.c_str()[0] == '#') { - labels[word] = vm.memory_ptr; - goto next; - } - - { - auto command = get_command(word); - if(command.has_value()) { - auto value = command.value(); - vm.push_byte(value.op); - - if(value.arguments > 0) { - for(int j = 1; j <= value.arguments; j++) { - auto arg = words.at(index + j); - Byte next_byte; - - if(arg.c_str()[0] == '#') { - next_byte = labels[arg]; - } else { - next_byte = stoi(arg); - } - - vm.push_byte(next_byte); - } - - index += value.arguments; - } - } else { - return {VM{0}, "Cannot find command"}; - } - } - - next: - index++; - } - - return {vm, nullptr}; - } - - std::optional get_command(const std::string& str) { - for(auto& command : operations) { - if(command.name == str) - return command; - } - - return {}; - } - }; - -} diff --git a/liamc/include/lexer.h b/liamc/include/lexer.h index 504c10ef..a71ff15c 100644 --- a/liamc/include/lexer.h +++ b/liamc/include/lexer.h @@ -4,6 +4,7 @@ #include #include #include +#include "liam.h" std::vector extract_chars(const char* path); @@ -55,12 +56,12 @@ std::string get_token_type_string(TokenType type); struct Token { TokenType type; - int line; - int character; + s32 line; + s32 character; std::string string; Token() = default; - Token(TokenType type, std::string string, int line, int character); + Token(TokenType type, std::string string, s32 line, s32 character); }; std::ostream& operator<<(std::ostream& os, const Token& token); @@ -71,9 +72,9 @@ struct Lexer { std::vector tokens; std::vector chars; - int current; - int current_line; - int current_character; + s32 current; + s32 current_line; + s32 current_character; std::filesystem::path path; Lexer(std::filesystem::path path); diff --git a/liamc/include/liam.h b/liamc/include/liam.h index 69d55a40..4b662e09 100644 --- a/liamc/include/liam.h +++ b/liamc/include/liam.h @@ -1,84 +1,62 @@ #pragma once -#include -#include -#include -#include #include +#include -typedef uint64_t Byte; +typedef int8_t s8; +typedef uint8_t u8; -template -struct Slice { - T* start; - size_t count; -}; +typedef int16_t s16; +typedef uint16_t u16; -template -struct Array { - T* start; - size_t count; - size_t capacity; +typedef int32_t s32; +typedef uint32_t u32; - Array() { - this->count = 0; - this->capacity = 10; - this->start = (T*)malloc(sizeof(T) * this->capacity); - } +typedef int64_t s64; +typedef uint64_t u64; - Array(size_t capacity) { - this->count = 0; - this->capacity = capacity; - this->start = (T*)malloc(sizeof(T) * capacity); - } +void panic(const std::string& msg); - void add(T value) { - maybe_expand(); - count++; - start[count - 1] = value; - } +#define TIME_START(name) \ + auto name = std::chrono::high_resolution_clock::now(); - void maybe_expand() { - if(count >= capacity) { - capacity *= 2; - start = (T*)realloc(start, capacity); - } - } +#define TIME_END(name, message) \ + {auto end = std::chrono::high_resolution_clock::now(); \ + std::chrono::duration delta = end - name; \ + std::cout << message << " :: " << delta.count() << "ms\n";} - void print() { - if(count > 0) { - for(int i = 0; i < count; i++) { - printf("%d", start[i]); - } - printf("\n"); - } +#define TRY(type, value, func) \ + type value = nullptr; \ + { \ + auto [ptr, error] = func; \ + if(error) { \ + return {nullptr, true}; \ + } \ + value = ptr; \ } -}; -enum OpCode : Byte { - ADD = 0, - PRINT = 1, - PUSH = 2, - GOTO = 3, -}; +#define NAMED_TOKEN(value, type) \ + Token* value = nullptr; \ + { \ + auto tuple = consume_token_of_type(type); \ + value = std::get<0>(tuple); \ + auto try_error = std::get<1>(tuple); \ + if(try_error) { \ + return {nullptr, true}; \ + } \ + } -struct VM -{ - Byte byte_code[1024] = {0}; - Byte stack[1024] = {0}; - Byte stack_ptr = 0; // one more then last valid value - Byte memory_ptr = 0; // one more then last valid byte - Byte instruction_ptr = 0; // current valid instruction +#define TRY_TOKEN(type) \ + { \ + auto [_, _try_error_] = consume_token_of_type(type); \ + if(_try_error_) { \ + return {nullptr, true}; \ + } \ + } - void push_byte(Byte byte); - void run(); - void add_op(); - void print_op(); - void push_op(); - void goto_op(); - Byte next_byte(); - void stack_push(Byte byte); - Byte stack_pop(); -}; +#define WIN(value) \ + {value, false} -void panic(const std::string& msg); \ No newline at end of file +#define FAIL(file, line, character, message) \ + ErrorReporter::report_error(file, line, character, message); \ + return {nullptr, true}; \ No newline at end of file diff --git a/liamc/include/macros.h b/liamc/include/macros.h deleted file mode 100644 index f551bbf9..00000000 --- a/liamc/include/macros.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#define TIME_START(name) \ - auto name = std::chrono::high_resolution_clock::now(); - -#define TIME_END(name, message) \ - {auto end = std::chrono::high_resolution_clock::now(); \ - std::chrono::duration delta = end - name; \ - std::cout << message << " :: " << delta.count() << "ms\n";} - -#define TRY(type, value, func) \ - type value = nullptr; \ - { \ - auto [ptr, error] = func; \ - if(error) { \ - return {nullptr, true}; \ - } \ - value = ptr; \ - } - -#define NAMED_TOKEN(value, type) \ - Token* value = nullptr; \ - { \ - auto tuple = consume_token_of_type(type); \ - value = std::get<0>(tuple); \ - auto try_error = std::get<1>(tuple); \ - if(try_error) { \ - return {nullptr, true}; \ - } \ - } - -#define TRY_TOKEN(type) \ - { \ - auto [_, _try_error_] = consume_token_of_type(type); \ - if(_try_error_) { \ - return {nullptr, true}; \ - } \ - } - -#define WIN(value) \ - {value, false} - -#define FAIL(file, line, character, message) \ - ErrorReporter::report_error(file, line, character, message); \ - return {nullptr, true}; \ No newline at end of file diff --git a/liamc/include/parser.h b/liamc/include/parser.h index acabd9f4..f3dbc8a9 100644 --- a/liamc/include/parser.h +++ b/liamc/include/parser.h @@ -5,8 +5,8 @@ #include "lexer.h" #include "statement.h" #include "expression.h" -#include "liam.h" #include +#include "liam.h" struct Statement; struct LetStatement; @@ -33,7 +33,7 @@ struct File { struct Parser { std::vector tokens; - int current; + s32 current; std::filesystem::path path; Parser(std::filesystem::path path, std::vector& tokens); @@ -47,7 +47,7 @@ struct Parser { std::tuple eval_struct_statement(); std::tuple eval_fn_statement(); std::tuple eval_loop_statement(); - int find_balance_point(TokenType push, TokenType pull, int from); + s32 find_balance_point(TokenType push, TokenType pull, s32 from); std::tuple eval_insert_statement(); std::tuple eval_return_statement(); std::tuple eval_break_statement(); @@ -79,7 +79,7 @@ struct Parser { std::tuple eval_array_type_expression(); bool match(TokenType type); - inline Token* peek(int offset = 0); + inline Token* peek(s32 offset = 0); Token* consume_token(); std::tuple consume_token_of_type(TokenType type); std::tuple, bool> consume_arguments(TokenType closer); diff --git a/liamc/include/statement.h b/liamc/include/statement.h index b0421d24..da97f9c5 100644 --- a/liamc/include/statement.h +++ b/liamc/include/statement.h @@ -1,7 +1,6 @@ #pragma once #include "lexer.h" -#include "liam.h" #include "expression.h" struct Expression; diff --git a/liamc/src/errors.cpp b/liamc/src/errors.cpp index 7302f655..fd6b26b1 100644 --- a/liamc/src/errors.cpp +++ b/liamc/src/errors.cpp @@ -1,6 +1,6 @@ #include "errors.h" - #include +#include "liam.h" ErrorReporter* ErrorReporter::singleton = nullptr; @@ -9,7 +9,7 @@ ErrorReporter() { reports = std::vector(); } -void ErrorReporter::report_error(std::string file, int line, int character, std::string message) { +void ErrorReporter::report_error(std::string file, s32 line, s32 character, std::string message) { if(ErrorReporter::singleton == nullptr) { ErrorReporter::singleton = new ErrorReporter(); diff --git a/liamc/src/lexer.cpp b/liamc/src/lexer.cpp index c6e46f9b..1a8f73fc 100644 --- a/liamc/src/lexer.cpp +++ b/liamc/src/lexer.cpp @@ -1,5 +1,6 @@ #include "lexer.h" #include +#include "liam.h" char* TokenTypeStrings[38] = { "int Literal", @@ -51,7 +52,7 @@ std::vector extract_chars(const char* path) { std::cout << "cannot open file"; } - for (int i = file.get(); i != EOF; i = file.get()) + for (s32 i = file.get(); i != EOF; i = file.get()) { vec.push_back((char)i); } @@ -60,7 +61,7 @@ std::vector extract_chars(const char* path) { return vec; } -Token::Token(TokenType type, std::string string, int line, int character) { +Token::Token(TokenType type, std::string string, s32 line, s32 character) { this->type = type; this->string = string; this->line = line; @@ -190,7 +191,7 @@ void Lexer::lex() { } break; default: - int word_start = current_character; + s32 word_start = current_character; auto word = get_word(); // check keywords @@ -293,7 +294,7 @@ void Lexer::lex() { // check numbers try { - int i = std::stoi(word); + s32 i = std::stoi(word); tokens.emplace_back(Token(TokenType::TOKEN_INT_LITERAL, word, current_line, word_start)); continue; } diff --git a/liamc/src/liam.cpp b/liamc/src/liam.cpp index 09c9bffa..34e0ee12 100644 --- a/liamc/src/liam.cpp +++ b/liamc/src/liam.cpp @@ -1,55 +1,6 @@ #include "liam.h" #include -void VM::push_byte(Byte byte) { - byte_code[memory_ptr] = byte; - memory_ptr++; -} - -void VM::run() { - while (instruction_ptr < memory_ptr) { - switch (byte_code[instruction_ptr]) - { - case OpCode::ADD: add_op(); instruction_ptr++; break; - case OpCode::PRINT: print_op(); instruction_ptr++; break; - case OpCode::PUSH: push_op(); instruction_ptr++; break; - case OpCode::GOTO: goto_op(); break; - } - } -} - -void VM::add_op() { - auto l = stack_pop(); - auto r = stack_pop(); - stack_push(l + r); -} - -void VM::print_op() { - printf("%lu\n", stack[stack_ptr - 1]); -} - -void VM::push_op() { - stack_push(next_byte()); -} - -void VM::goto_op() { - Byte to = next_byte(); - instruction_ptr = to; -} - -Byte VM::next_byte() { - return byte_code[++instruction_ptr]; -} - -void VM::stack_push(Byte byte) { - stack[stack_ptr] = byte; - stack_ptr++; -} - -Byte VM::stack_pop() { - return stack[--stack_ptr]; -} - void panic(const std::string& msg) { std::cerr << msg << std::endl; diff --git a/liamc/src/main.cpp b/liamc/src/main.cpp index a60fa822..75cabaa7 100644 --- a/liamc/src/main.cpp +++ b/liamc/src/main.cpp @@ -4,9 +4,8 @@ #include "liam.h" #include "rust_backend/rust_backend.h" #include "compiler.h" -#include "macros.h" -int main(int argc, char** argv) { +s32 main(s32 argc, char** argv) { if (argc < 2) { panic("Not enough arguments"); diff --git a/liamc/src/parser.cpp b/liamc/src/parser.cpp index a1524c94..c4c7c45e 100644 --- a/liamc/src/parser.cpp +++ b/liamc/src/parser.cpp @@ -1,8 +1,8 @@ #include "parser.h" #include #include -#include "macros.h" #include "errors.h" +#include "liam.h" File:: File(std::filesystem::path path) { @@ -111,7 +111,7 @@ std::tuple Parser:: eval_scope_statement() { auto statements = std::vector(); NAMED_TOKEN(open_brace, TOKEN_BRACE_OPEN); - int closing_brace_index = find_balance_point(TOKEN_BRACE_OPEN, TOKEN_BRACE_CLOSE, current - 1); + s32 closing_brace_index = find_balance_point(TOKEN_BRACE_OPEN, TOKEN_BRACE_CLOSE, current - 1); if (closing_brace_index == current + 1) { // if this scope is empty current++; } else if(closing_brace_index < 0) { @@ -153,10 +153,10 @@ eval_loop_statement() { return WIN(new LoopStatement(*identifier, body)); } -int Parser:: -find_balance_point(TokenType push, TokenType pull, int from) { - int current_index = from; - int balance = 0; +s32 Parser:: +find_balance_point(TokenType push, TokenType pull, s32 from) { + s32 current_index = from; + s32 balance = 0; while (current_index < tokens.size()) { if (tokens.at(current_index).type == push) { @@ -485,7 +485,7 @@ match(TokenType type) { } Token* Parser:: -peek(int offset) { +peek(s32 offset) { return &tokens.at(current + offset); } diff --git a/liamc/src/rust_backend/rust_backend.cpp b/liamc/src/rust_backend/rust_backend.cpp index 8ac9dd5b..5966507a 100644 --- a/liamc/src/rust_backend/rust_backend.cpp +++ b/liamc/src/rust_backend/rust_backend.cpp @@ -28,89 +28,48 @@ emit(File* file) { std::string RustBackend:: emit_statement(Statement* statement) { - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_insert_statement(ptr); - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_return_statement(ptr); - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_break_statement(ptr); - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_let_statement(ptr); - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - auto s = emit_fn_statement(ptr); - return s; - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - auto s = emit_loop_statement(ptr); - return s; - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - auto s = emit_struct_statement(ptr); - return s; - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - auto s = emit_assigment_statement(ptr); - return s; - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_expression_statement(ptr); - } - } - - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_for_statement(ptr); - } + switch (statement->statement_type) { + case StatementType::STATEMENT_INSERT: + return emit_insert_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_RETURN: + return emit_return_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_BREAK: + return emit_break_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_LET: + return emit_let_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_FN: + return emit_fn_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_SCOPE: + return emit_scope_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_LOOP: + return emit_loop_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_STRUCT: + return emit_struct_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_ASSIGNMENT: + return emit_assigment_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_EXPRESSION: + return emit_expression_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_FOR: + return emit_for_statement(dynamic_cast(statement)); + break; + case StatementType::STATEMENT_IF: + return emit_if_statement(dynamic_cast(statement)); + break; } - { - auto ptr = dynamic_cast(statement); - if (ptr) { - return emit_if_statement(ptr); - } - } panic("Statement not implemented in rust back end :["); - return nullptr; + return ""; } std::string RustBackend:: @@ -161,7 +120,7 @@ emit_fn_statement(FnStatement* statement) { fn_source.append(statement->identifier.string); fn_source.append("("); - int index = 0; + s32 index = 0; for (auto& [identifier, type] : statement->params) { fn_source.append(identifier.string + ": " + emit_type_expression(type)); index++; @@ -200,7 +159,7 @@ emit_struct_statement(StructStatement* statement) { // struct impl block source.append("impl " + statement->identifier.string + " {"); source.append("fn new("); - for (int i = 0; i < statement->members.size(); i++) { + for (s32 i = 0; i < statement->members.size(); i++) { auto& [identifier, type] = statement->members.at(i); source.append(identifier.string + ": " + emit_type_expression(type)); @@ -210,7 +169,7 @@ emit_struct_statement(StructStatement* statement) { } source.append(") -> Self {"); source.append("Self{"); - for (int i = 0; i < statement->members.size(); i++) { + for (s32 i = 0; i < statement->members.size(); i++) { auto& [identifier, _] = statement->members.at(i); source.append(identifier.string); if(i + 1 < statement->members.size()) { @@ -374,7 +333,7 @@ emit_call_expression(CallExpression* expression) { auto source = std::string(); auto identifier = dynamic_cast(expression->identifier); source.append(identifier->identifier.string + "("); - int index = 0; + s32 index = 0; for (auto expr : expression->args) { source.append(emit_cloneable_expression(expr)); index++; @@ -389,14 +348,6 @@ emit_call_expression(CallExpression* expression) { std::string RustBackend:: emit_unary_expression(UnaryExpression* expression) { - // int x = 10; - // int* a = &x; - // int b = *a; - - // let x: u64 = 10; - // let a: u64^ = @x; - // let b: u64 = *a; - if (expression->op.type == TOKEN_AT) { return "(&mut " + emit_expression(expression->expression) + ") as *mut _"; } @@ -421,7 +372,7 @@ emit_get_expression(GetExpression* expression) { std::string RustBackend:: emit_new_expression(NewExpression* expression) { std::string source = expression->identifier.string + "::new("; - int index = 0; + s32 index = 0; for (auto expr : expression->expressions) { source.append(emit_cloneable_expression(expr)); index++; @@ -437,7 +388,7 @@ emit_new_expression(NewExpression* expression) { std::string RustBackend:: emit_array_expression(ArrayExpression* expression) { std::string source = "vec!["; - int index = 0; + s32 index = 0; for (auto expr : expression->expressions) { source.append(emit_cloneable_expression(expr)); index++; diff --git a/liamc/src/type_checker.cpp b/liamc/src/type_checker.cpp index 72d49ad5..2dd0a2bf 100644 --- a/liamc/src/type_checker.cpp +++ b/liamc/src/type_checker.cpp @@ -1,5 +1,6 @@ #include "type_checker.h" #include "parser.h" +#include "liam.h" SymbolTable:: SymbolTable() { @@ -409,7 +410,7 @@ type_check_call_expression(CallExpression* expression, SymbolTable* symbol_table panic("Incorrect numbers of args passed to function call"); } - for (int i = 0; i < fn_type_info->args.size(); i++) { + for (s32 i = 0; i < fn_type_info->args.size(); i++) { if (!type_match(fn_type_info->args.at(i), arg_type_infos.at(i))) { panic("Type mismatch at function call"); } @@ -488,7 +489,7 @@ type_check_new_expression(NewExpression* expression, SymbolTable* symbol_table) } // check types - for (int i = 0; i < members_type_info.size(); i++) { + for (s32 i = 0; i < members_type_info.size(); i++) { auto [member, type] = struct_type_info->members.at(i); if (!type_match(members_type_info.at(i), type)) { panic("Incorect arguments to new constructor"); @@ -512,7 +513,7 @@ type_check_array_expression(ArrayExpression* expression, SymbolTable* symbol_tab } if(expression->expressions.size() > 1) { - for(int i = 0; i < expression->expressions.size(); i++) { + for(s32 i = 0; i < expression->expressions.size(); i++) { if(!type_match(array_member_type, expression->expressions.at(i)->type_info)) { panic("Mismatched types in array expression, index " + std::to_string(i) + " has unexpected return_type"); } @@ -615,7 +616,7 @@ bool type_match(TypeInfo* a, TypeInfo* b) { auto fn_b = static_cast(b); if (type_match(fn_a->return_type, fn_b->return_type)) { - for (int i = 0; i < fn_a->args.size(); i++) { + for (s32 i = 0; i < fn_a->args.size(); i++) { if(type_match(fn_a->args.at(i), fn_b->args.at(i))) {} else { return false; } } @@ -629,7 +630,7 @@ bool type_match(TypeInfo* a, TypeInfo* b) { auto struct_a = static_cast(a); auto struct_b = static_cast(b); - for (int i = 0; i < struct_a->members.size(); i++) { + for (s32 i = 0; i < struct_a->members.size(); i++) { auto [a_member, a_type] = struct_a->members.at(i); auto [b_member, b_type] = struct_b->members.at(i); if (!type_match(a_type, b_type)) {