From 762c03458e73b9850ec7225121620c1151ae11ab Mon Sep 17 00:00:00 2001 From: John Easterday Date: Sun, 5 Jun 2022 17:43:26 -0400 Subject: [PATCH] Switched to rust --- .gitattributes | 0 .gitignore | 15 +- CMakeLists.txt | 12 - Cargo.lock | 7 + Cargo.toml | 8 + LICENSE | 0 README.md | 15 - examples/collatz.sea | 31 ++ examples/fibonacci.sea | 10 + examples/hello_world.sea | 3 + examples/rational.sea | 46 ++ src/CMakeLists.txt | 39 -- src/ast.cpp | 976 ------------------------------------- src/ast.hpp | 629 ------------------------ src/compiler/errors.rs | 185 +++++++ src/compiler/lexer.rs | 310 ++++++++++++ src/compiler/mod.rs | 58 +++ src/compiler/parser/ast.rs | 0 src/compiler/parser/mod.rs | 0 src/helper.hpp | 64 --- src/lib.rs | 1 + src/main.cpp | 53 -- src/main.rs | 16 + src/ocean.l | 209 -------- src/ocean.y | 347 ------------- src/symboltable.cpp | 343 ------------- src/symboltable.hpp | 141 ------ src/token.hpp | 141 ------ src/type_helper.hpp | 13 - src/typechecker.cpp | 955 ------------------------------------ tests/hello_world.rs | 6 + tests/test.sea | 49 -- tests/test2.sea | 8 - 33 files changed, 685 insertions(+), 4005 deletions(-) mode change 100644 => 100755 .gitattributes mode change 100644 => 100755 .gitignore delete mode 100644 CMakeLists.txt create mode 100644 Cargo.lock create mode 100644 Cargo.toml mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md create mode 100644 examples/collatz.sea create mode 100644 examples/fibonacci.sea create mode 100644 examples/hello_world.sea create mode 100644 examples/rational.sea delete mode 100644 src/CMakeLists.txt delete mode 100644 src/ast.cpp delete mode 100644 src/ast.hpp create mode 100644 src/compiler/errors.rs create mode 100644 src/compiler/lexer.rs create mode 100644 src/compiler/mod.rs create mode 100644 src/compiler/parser/ast.rs create mode 100644 src/compiler/parser/mod.rs delete mode 100644 src/helper.hpp create mode 100644 src/lib.rs delete mode 100644 src/main.cpp create mode 100644 src/main.rs delete mode 100644 src/ocean.l delete mode 100644 src/ocean.y delete mode 100644 src/symboltable.cpp delete mode 100644 src/symboltable.hpp delete mode 100644 src/token.hpp delete mode 100644 src/type_helper.hpp delete mode 100644 src/typechecker.cpp create mode 100644 tests/hello_world.rs delete mode 100644 tests/test.sea delete mode 100644 tests/test2.sea diff --git a/.gitattributes b/.gitattributes old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 86c8ac4..553b64d --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,7 @@ .vscode/* -CMakeFiles/* -*/CMakeFiles/* -*.cmake -*/Makefile -Makefile -CMakeCache.txt -ocean -src/ocean.tab.cpp -src/ocean.tab.hpp -src/lex.yy.cpp +scratch/* -*/*.output +# Added by cargo + +/target diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index f4270c0..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -cmake_minimum_required(VERSION 3.19) - -#set project name -project(ocean VERSION 1.0) - -set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set (CMAKE_BUILD_TYPE RelWithDebInfo) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -add_subdirectory(src) diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..09b2264 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ocean" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2061b27 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ocean" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 37d18ac..1629908 --- a/README.md +++ b/README.md @@ -1,19 +1,4 @@ # ocean A C-like programming language (get it like sea-like like an ocean lol) -### Building -This project uses flex and bison so install them. _add some instructions about this_ -Then in the root folder of this repo run: - -```cmake .``` - -to build the makefile then: - -```make``` - -to build the project then - -```{install???}``` - -to install. diff --git a/examples/collatz.sea b/examples/collatz.sea new file mode 100644 index 0000000..43dc580 --- /dev/null +++ b/examples/collatz.sea @@ -0,0 +1,31 @@ +isEven: func = (x: i64) -> (result: bool = x % 2 == 0) + +isEmpty: func = (x: string) -> (result: bool = x == "") + +collatz: func = (input: i64) -> (path: i64[]) { + loop input != 1 { + path.append(input) + if !input.isEven() { + input = input / 2 + } else { + input = 3 * input + 1 + } + } +} + +while true { + print("Input a number: ") + userinput: string = input() + if !userinput.isEmpty() { + parsed: auto = userInput.parsei64 # the type here is optional i64 + if parsed.has_value() { + result: auto = parsed.collatz() + println(result.size()) + println(result) + break + } + println(`{userinput} is not an integer`) + } else { + println("not a number") + } +} diff --git a/examples/fibonacci.sea b/examples/fibonacci.sea new file mode 100644 index 0000000..b95322b --- /dev/null +++ b/examples/fibonacci.sea @@ -0,0 +1,10 @@ +fib: func = (input: i64) -> (result: i64) { + if input == 0 { + result = 0 + } else { + result = input + fib(input - 1) + } +} + +println(9.fib) +println(fib(10)) \ No newline at end of file diff --git a/examples/hello_world.sea b/examples/hello_world.sea new file mode 100644 index 0000000..50a246c --- /dev/null +++ b/examples/hello_world.sea @@ -0,0 +1,3 @@ +use io + +println("Hello, World!") \ No newline at end of file diff --git a/examples/rational.sea b/examples/rational.sea new file mode 100644 index 0000000..85b2af7 --- /dev/null +++ b/examples/rational.sea @@ -0,0 +1,46 @@ +gcd: func = (a: i64, b: i64) -> (result: i64) { + # If A=0 then GCD(A, B)=B since the Greatest Common Divisor of 0 and B is B. + # If B=0 then GCD(a,b)=a since the Greatest Common Divisor of 0 and a is a. + # Let R be the remainder of dividing A by B assuming A > B. (R = A % B) + # Find GCD( B, R ) because GCD( A, B ) = GCD( B, R ). Use the above steps again. + + loop a != 0 || b != 0 { + new_a: i64 = b + new_b: i64 = a % b + } + + if a == 0 { + result = b + } else if b == 0 { + result = a + } +} + +abs: func = (a: i64) -> (result: i64) { + if a < 0 { + result = -a + } else { + result = a + } +} + +lcm: func = (a: i64, b: i64) -> (result: i64 = abs(a) * abs(b) / gcd(a, b)) + +op _+_ left = (x: auto T, y: T) -> (result: T = add(x, y)) + +op _-_ left = (x: auto T, y: T) -> (result: T = subtract(x, y)) + +pack rational { + numerator: i64 + denominator: i64 +} + +add: func = (a: rational, b: rational) -> (result: rational) { + mul: i64 = lcm(a.denominator, b.denominator) + res = { a.numerator * mul + b.numerator * mul, mul }; +} + +subtract: func = (a: rational, b: rational) -> (res: rational) { + mul: i64 = lcm(a.denominator, b.denominator) + res = { a.numerator * mul - b.numerator * mul, mul }; +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index bf5790c..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -#compiler definitions -add_compile_definitions( - DEBUG_MESSAGES - DEBUG_AST -) - -#source files -set(SOURCES - main.cpp - ast.cpp - symboltable.cpp - typechecker.cpp -) - -#find packages -find_package(BISON REQUIRED) -find_package(FLEX REQUIRED) - -if(NOT BISON_FOUND) - message (FATAL_ERROR "BISON WAS NOT FOUND!!!!!") -else() - message("bison was found :)") -endif() - -if(NOT FLEX_FOUND) - message (FATAL_ERROR "FLEX WAS NOT FOUND!!!!!") -else() - message("flex was found :)") -endif() - -BISON_TARGET(OCEAN_PARSER ocean.y ${CMAKE_CURRENT_BINARY_DIR}/ocean.tab.cpp COMPILE_FLAGS -Wcounterexamples VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/ocean.output) -FLEX_TARGET(OCEAN_SCANNER ocean.l ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.cpp) -ADD_FLEX_BISON_DEPENDENCY(OCEAN_SCANNER OCEAN_PARSER) - -add_executable(ocean - ${SOURCES} - ${BISON_OCEAN_PARSER_OUTPUTS} - ${FLEX_OCEAN_SCANNER_OUTPUTS} -) diff --git a/src/ast.cpp b/src/ast.cpp deleted file mode 100644 index 97cd91d..0000000 --- a/src/ast.cpp +++ /dev/null @@ -1,976 +0,0 @@ -#include "ast.hpp" - -#include -#include - -/** VarType toCastString **/ -std::string BaseType::toCastString() { - return std::string(_type->lexeme.string_lex) + (_auto_name ? "-" + std::string(_auto_name->lexeme.string_lex) : ""); -} - -std::string CustomType::toCastString() { - return _type->toCastString(); -} - -std::string FuncType::toCastString() { - std::string params = "("; - for(int i = 0; i < _param_types->size(); i++) { - params += (*_param_types)[i]->toCastString(); - if (i != _param_types->size() - 1) - params += "+"; - } - params += ")"; - std::string returns = "("; - for(int i = 0; i < _return_types->size(); i++) { - returns += (*_return_types)[i]->toCastString(); - if (i != _return_types->size() - 1) - returns += "+"; - } - returns += ")"; - return "func" + params + returns; -} - -std::string ConstType::toCastString() { - return _type->toCastString() + "-c"; -} - -std::string PointerType::toCastString() { - return _type->toCastString() + "-p"; -} - -std::string ArrayType::toCastString() { - return _type->toCastString() + "-a"; -} - -std::string Variable::toCastString() { - return std::string(_name->lexeme.string_lex) + ":" + _var->toCastString(); -} - -/** Create Error List **/ -void BaseType::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - std::stringstream ss; - if (symbol->errorType == ErrorType::None) { - //shouldn't happen since we don't do the type checking in the var - ss << "Error [] lower in tree from Custom Type node" << std::endl; - } else { - ss << "Error [ " << _type->linenum << ", " << _type->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - } - error_list->push_back(ss.str()); - } -} - -void CustomType::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - std::stringstream ss; - if (symbol->errorType == ErrorType::None) { - //shouldn't happen since we don't do the type checking in the var - ss << "Error [] lower in tree from Custom Type node" << std::endl; - } else { - ss << "Error [ " << _type->_name->linenum << ", " << _type->_name->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - } - error_list->push_back(ss.str()); - } -} - -void FuncType::getErrors(std::vector* error_list) { - for (auto param : *_param_types) { - param->getErrors(error_list); - } - - for (auto ret : *_return_types) { - ret->getErrors(error_list); - } -} - -void ConstType::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _type->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in ConstType." << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void PointerType::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _type->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in PointerType." << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void ArrayType::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _type->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void Parameter::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _type->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in Parameter." << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void Program::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - for (auto stmt : *_stmts) { - stmt->getErrors(error_list); - } - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in Program." << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void Macro::getErrors(std::vector* error_list) { /*NONE*/ } - -void CompoundStmt::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - for (auto stmt : *_stmts) { - stmt->getErrors(error_list); - } - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in CompoundStmt." << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void VarDec::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _type->getErrors(error_list); - if (_expr) _expr->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << _id->linenum << ", " << _id->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - ss << "\t" << "Left-Hand Side: " << _type->symbol->toString() << std::endl; - ss << "\t" << "Right-Hand Side: " << (_expr ? _expr->symbol->toString() : "There was no right-hand side :(") << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void FuncDec::getErrors(std::vector* error_list) { - //get parameter errors - for (auto param : *_params) { - param->getErrors(error_list); - } - - for (auto ret : *_returns) { - ret->getErrors(error_list); - } - - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _body->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void OpFuncDec::getErrors(std::vector* error_list) { - for (auto param : *_params) { - param->getErrors(error_list); - } - - for (auto ret : *_returns) { - ret->getErrors(error_list); - } - - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _body->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void CastFuncDec::getErrors(std::vector* error_list) { - for (auto param : *_params) { - param->getErrors(error_list); - } - - for (auto ret : *_returns) { - ret->getErrors(error_list); - } - - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _body->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void EnumDec::getErrors(std::vector* error_list) {/* oof */} - -void PackDec::getErrors(std::vector* error_list) {/* oof */} - -void VariantDec::getErrors(std::vector* error_list) {/* oof */} - -void IfStmt::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _body->getErrors(error_list); - if(_elseBody) _elseBody->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void SwitchCase::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - if (_case) _case->getErrors(error_list); - _body->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void SwitchStmt::getErrors(std::vector* error_list) { - _cond->getErrors(error_list); - - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - for (auto scase : *_cases) { - scase->getErrors(error_list); - } - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in SwitchStmt" << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void WhileStmt::getErrors(std::vector* error_list) { - _cond->getErrors(error_list); - - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _body->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << _start->linenum << ", " << _start->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void ForStmt::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _iter->getErrors(error_list); - if (_by) _by->getErrors(error_list); - _body->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << _start->linenum << ", " << _start->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void ExprStmt::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _expr->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error : TypeChecker Issue :( ... Unhandled error in ExprStmt" << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void StopStmt::getErrors(std::vector* error_list) {/* no freaking way */} - -void BreakStmt::getErrors(std::vector* error_list) {/* no freaking way */} - -void ContinueStmt::getErrors(std::vector* error_list) {/* no freaking way */} - -void Variable::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - error_list->push_back("Error : Found a none in the variable node :("); - } else { - std::stringstream ss; - ss << "Error [ " << _name->linenum << ", " << _name->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void MemberAccess::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _parent->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void ArrayAccess::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _parent->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void Call::getErrors(std::vector* error_list) { - //TODO - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); -} - -void Assignment::getErrors(std::vector* error_list) { - //TODO - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); -} - -void BinaryExpr::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _left->getErrors(error_list); - _right->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << _op->linenum << ", " << _op->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - ss << "\t" << "Operator: " << _op->lexeme.string_lex << std::endl; - ss << "\t" << "Left-Hand Side: " << _left->symbol->toString() << std::endl; - ss << "\t" << "Right-Hand Side: " << _right->symbol->toString() << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void UnaryExpr::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - _expr->getErrors(error_list); - } else { - std::stringstream ss; - ss << "Error [ " << _op->linenum << ", " << _op->colnum << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void Cast::getErrors(std::vector* error_list) {} - -void IntValue::getErrors(std::vector* error_list) {/* quit jokin */} - -void HexValue::getErrors(std::vector* error_list) {/* quit jokin */} - -void BoolValue::getErrors(std::vector* error_list) {/* quit jokin */} - -void FloatValue::getErrors(std::vector* error_list) {/* quit jokin */} - -void StringValue::getErrors(std::vector* error_list) {/* quit jokin */} - -void ArrayValue::getErrors(std::vector* error_list) { - if (symbol->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - for (auto elem : *_elements) { - elem->getErrors(error_list); - } - } else { - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); - } - } -} - -void ObjectValue::getErrors(std::vector* error_list) { - //TODO - std::stringstream ss; - ss << "Error [ " << "linenum" << ", " << "colnum" << " ]: " << ErrorString(symbol->errorType) << std::endl; - ss << "\t" << symbol->name << std::endl; - error_list->push_back(ss.str()); -} - -/** NODE TYPE FUNCTIONS **/ - -std::string BaseType::getNodeType() { return "BaseType"; } - -std::string CustomType::getNodeType() { return "CustomType"; } - -std::string FuncType::getNodeType() { return "FuncType"; } - -std::string ConstType::getNodeType() { return "ConstType"; } - -std::string PointerType::getNodeType() { return "PointerType"; } - -std::string ArrayType::getNodeType() { return "ArrayType"; } - -std::string Parameter::getNodeType() { return "Parameter"; } - -std::string Program::getNodeType() { return "Program"; } - -std::string Macro::getNodeType() { return "Macro"; } - -std::string CompoundStmt::getNodeType() { return "Compound"; } - -std::string VarDec::getNodeType() { return "VarDec"; } - -std::string FuncDec::getNodeType() { return "FuncDec"; } - -std::string OpFuncDec::getNodeType() { return "OpFuncDec"; } - -std::string CastFuncDec::getNodeType() { return "CastFuncDec"; } - -std::string EnumDec::getNodeType() { return "EnumDec"; } - -std::string PackDec::getNodeType() { return "PackDec"; } - -std::string VariantDec::getNodeType() { return "VariantDec"; } - -std::string IfStmt::getNodeType() { return "If"; } - -std::string SwitchCase::getNodeType() { return "Case"; } - -std::string SwitchStmt::getNodeType() { return "Switch"; } - -std::string WhileStmt::getNodeType() { return "While"; } - -std::string ForStmt::getNodeType() { return "For"; } - -std::string ExprStmt::getNodeType() { return "Expr"; } - -std::string StopStmt::getNodeType() { return "Stop"; } - -std::string BreakStmt::getNodeType() { return "Break"; } - -std::string ContinueStmt::getNodeType() { return "Continue"; } - -std::string Variable::getNodeType() { return "Variable"; } - -std::string MemberAccess::getNodeType() { return "MemberAccess"; } - -std::string ArrayAccess::getNodeType() { return "ArrayAccess"; } - -std::string Call::getNodeType() { return "Call"; } - -std::string Assignment::getNodeType() { return "Assignment"; } - -std::string BinaryExpr::getNodeType() { return "Binary"; } - -std::string UnaryExpr::getNodeType() { return "Unary"; } - -std::string Cast::getNodeType() { return "Cast"; } - -std::string IntValue::getNodeType() { return "Int"; } - -std::string HexValue::getNodeType() { return "Hex"; } - -std::string BoolValue::getNodeType() { return "Bool"; } - -std::string FloatValue::getNodeType() { return "Float"; } - -std::string StringValue::getNodeType() { return "String"; } - -std::string ArrayValue::getNodeType() { return "Array"; } - -std::string ObjectValue::getNodeType() { return "Object"; } - -/** toString FUNCTIONS **/ - -//! The following functions are not great and will result in a major performance hit -//! (but we shouldn't be converting the entire ast to a string very often if even more than once) -//! However... I am not at the point of optimizing code and it seems like something I can do later -//! This comment recognizing the issue will hold me accountable and I accept that my future self will -//! be ashamed with me - -std::string BaseType::toString() { - std::string results = "(BaseType: "; - if (_type) results += _type->toString(); - if (_auto_name) results += " (Name: " + _auto_name->toString() + ")"; - results += ")"; - return results; -} - -std::string CustomType::toString() { - std::string results = "(CustomType: "; - if (_type) results += _type->toString(); - results += ")"; - return results; -} - -std::string FuncType::toString() { - std::string results = "(FuncType:"; - if (_param_types) { - results += " (ParamTypes:"; - for (auto ptype : *_param_types) { - results += " " + ptype->toString(); - } - results += ")"; - } - if (_return_types) { - results += " (ReturnTypes:"; - for (auto rtype : *_return_types) { - results += " " + rtype->toString(); - } - results += ")"; - } - results += ")"; - return results; -} - -std::string ConstType::toString() { - std::string results = "(Const: "; - if (_type) results += _type->toString(); - results += ")"; - return results; -} - -std::string PointerType::toString() { - std::string results = "(Pointer: "; - if (_type) results += _type->toString(); - results += ")"; - return results; -} - -std::string ArrayType::toString() { - std::string results = "(ArrayType: "; - if (_type) results += _type->toString(); - if (_array_length) { - results += " (Size: " + _array_length->toString() + ")"; - } - results += ")"; - return results; -} - -std::string Parameter::toString() { - std::string results = "(Parameter: "; - if (_id) results += "(Name: " + _id->toString() + ")"; - if (_type) { - results += " " + _type->toString(); - } - results += ")"; - return results; -} - -std::string Program::toString() { - std::string results = "(Program:"; - if (_stmts) { - for (auto stmt : *_stmts) { - results += " " + stmt->toString(); - } - } - results += ")"; - return results; -} - -std::string Macro::toString() { - std::string results = "(Macro: "; - if (_macro) results += _macro->toString(); - results += ")"; - return results; -} - -std::string CompoundStmt::toString() { - std::string results = "(Compound:"; - if (_stmts) { - for (auto stmt : *_stmts) { - results += " " + stmt->toString(); - } - } - results += ")"; - return results; -} - -std::string VarDec::toString() { - std::string results = "(VarDec: "; - if (_id) results += "(Name: " + _id->toString() + ")"; - if (_type) { - results += " " + _type->toString(); - } - if (_expr) { - results += " (Value: " + _expr->toString() + ")"; - } - results += ")"; - return results; -} - -std::string FuncDec::toString() { - std::string results = "(FuncDec: "; - if (_id) results += "(Name: " + _id->toString() + ")"; - if (_params) { - results += " (Params:"; - for (auto param : *_params) { - results += " " + param->toString(); - } - results += ")"; - } - if (_returns) { - results += " (Returns:"; - for (auto ret : *_returns) { - results += " " + ret->toString(); - } - results += ")"; - } - if (_body) results += " " + _body->toString(); - results += ")"; - return results; -} - -std::string OpFuncDec::toString() { - std::string results = "(OpFuncDec: "; - if (_op) results += "(Op: " + _op->toString() + ")"; - if (_params) { - results += " (Params:"; - for (auto param : *_params) { - results += " " + param->toString(); - } - results += ")"; - } - if (_returns) { - results += " (Returns:"; - for (auto ret : *_returns) { - results += " " + ret->toString(); - } - results += ")"; - } - if (_body) results += " " + _body->toString(); - results += ")"; - return results; -} - -std::string CastFuncDec::toString() { - std::string results = "(CastFuncDec: "; - if (_casting_type) results += "(Name: " + _casting_type->toString() + ")"; - if (_params) { - results += " (Params:"; - for (auto param : *_params) { - results += " " + param->toString(); - } - results += ")"; - } - if (_returns) { - results += " (Returns:"; - for (auto ret : *_returns) { - results += " " + ret->toString(); - } - results += ")"; - } - if (_body) results += " " + _body->toString(); - results += ")"; - return results; -} - -std::string EnumDec::toString() { - std::string results = "(Enum: "; - if (_id) results += "(Name: " + _id->toString() + ")"; - if (_base_type) results += " " + _base_type->toString(); - if (_declist) { - for (auto dec : *_declist) { - results += " " + dec->toString(); - } - } - results += ")"; - return results; -} - -std::string PackDec::toString() { - std::string results = "(Pack: "; - if (_id) results += "(Name: " + _id->toString() + ")"; - if (_declist) { - for (auto dec : *_declist) { - results += " " + dec->toString(); - } - } - results += ")"; - return results; -} - -std::string VariantDec::toString() { - std::string results = "(Variant: "; - if (_id) results += "(Name: " + _id->toString() + ")"; - if (_declist) { - for (auto dec : *_declist) { - results += " " + dec->toString(); - } - } - results += ")"; - return results; -} - -std::string IfStmt::toString() { - std::string results = "(If: "; - if (_cond) { - results += "(Condition: " + _cond->toString() + ")"; - } - if (_body) { - results += " (True: " + _body->toString() + ")"; - } - if (_elseBody) { - results += " (False: " + _elseBody->toString() + ")"; - } - results += ")"; - return results; -} - -std::string SwitchCase::toString() { - std::string results = "(SwitchCase: "; - if (_case) { - results += "(Case: " + _case->toString() + ")"; - } - if (_body) { - results += " " + _body->toString(); - } - results += ")"; - return results; -} - -std::string SwitchStmt::toString() { - std::string results = "(Switch: "; - if (_cond) { - results += "(Cond: " + _cond->toString() + ")"; - } - if (_cases) { - for (auto c : *_cases) { - results += " " + c->toString(); - } - } - results += ")"; - return results; -} - -std::string WhileStmt::toString() { - std::string results = "(While: "; - if (_cond) { - results += "(Cond: " + _cond->toString() + ")"; - } - if (_body) { - results += " " + _body->toString(); - } - results += ")"; - return results; -} - -std::string ForStmt::toString() { - std::string results = "(For: "; - if (_id) results += "(IterName: " + _id->toString() + ")"; - if (_iter) results += " (Iterable: " + _iter->toString() + ")"; - if (_by) results += " (By: " + _by->toString() + ")"; - if (_body) results += " " + _body->toString(); - results += ")"; - return results; -} - -std::string ExprStmt::toString() { - std::string results = "(Expr: "; - if (_expr) results += _expr->toString(); - results += ")"; - return results; -} - -std::string StopStmt::toString() { return "(Stop:)"; } -std::string BreakStmt::toString() { return "(Break:)"; } -std::string ContinueStmt::toString() { return "(Continue:)"; } - -std::string Variable::toString() { - std::string result = "(Variable: "; - if (!_var) { - if (_name) result += "(Name: " + _name->toString() + ")"; - } else { - if (_name) result += "(Namespace: " + _name->toString() + ")"; - if (_var) result += " " + _var->toString(); - } - result += ")"; - return result; -} - -std::string MemberAccess::toString() { - std::string result = "(MemberAccess: "; - if (_parent) result += _parent->toString(); - if (_id) result += " (MemberName: " + _id->toString() + ")"; - result += ")"; - return result; -} - -std::string ArrayAccess::toString() { - std::string result = "(ArrayAccess: "; - if (_parent) result += _parent->toString(); - if (_expr) result += " (Element: " + _expr->toString() + ")"; - result += ")"; - return result; -} - -std::string Call::toString() { - std::string result = "(Call: "; - if (_parent) result += _parent->toString(); - if (_args) { - result += " (Args:"; - for(auto arg : *_args) { - result += " " + arg->toString(); - } - result += ")"; - } - result += ")"; - return result; -} - -std::string Assignment::toString() { - std::string result = "(Assignment: "; - if (_op) result += "(Op: " + _op->toString() + ")"; - if (_var) result += _var->toString(); - if (_expr) result += " (Value: " +_expr->toString() + ")"; - result += ")"; - return result; -} - -std::string BinaryExpr::toString() { - std::string results = "(Binary: "; - if (_op) results += "(Op: " + _op->toString() + ")"; - if (_left) results += " " + _left->toString(); - if (_right) results += " " + _right->toString(); - results += ")"; - return results; -} - -std::string UnaryExpr::toString() { - std::string results = "(Unary: "; - if (_op) results += "(Op: " + _op->toString() + ")"; - if (_expr) results += " " + _expr->toString(); - results += ")"; - return results; -} - -std::string Cast::toString() { - std::string results = "(Cast: "; - if (_type) results += _type->toString(); - if (_expr) results += " " + _expr->toString(); - results += ")"; - return results; -} - -std::string IntValue::toString() { - std::string results = "(Int: "; - if (_value) results += _value->toString(); - results += ")"; - return results; -} - -std::string HexValue::toString() { - std::string results = "(Hex: "; - if (_value) results += _value->toString(); - results += ")"; - return results; -} - -std::string BoolValue::toString() { - std::string results = "(Bool: "; - if (_value) results += _value->toString(); - results += ")"; - return results; -} - -std::string FloatValue::toString() { - std::string results = "(Float: "; - if (_value) results += _value->toString(); - results += ")"; - return results; -} - -std::string StringValue::toString() { - std::string results = "(String: "; - if (_value) results += _value->toString(); - results += ")"; - return results; -} - -std::string ArrayValue::toString() { - std::string results = "(Array:"; - if (_elements) { - for (auto elem : *_elements) { - results += " " + elem->toString(); - } - } - results += ")"; - return results; -} - -std::string ObjectValue::toString() { - std::string results = "(ObjectInitialize:"; - if (_elements) { - for (auto elem : *_elements) { - results += " " + elem->toString(); - } - } - results += ")"; - return results; -} diff --git a/src/ast.hpp b/src/ast.hpp deleted file mode 100644 index d4220aa..0000000 --- a/src/ast.hpp +++ /dev/null @@ -1,629 +0,0 @@ -#pragma once - -#include -#include - -#include "token.hpp" -#include "symboltable.hpp" - -class AstNode { -public: - Symbol* symbol = nullptr; - - virtual std::string getNodeType() = 0; - virtual std::string toString() = 0; - virtual Symbol* buildSymbolTable(SymbolTable* table) = 0; - virtual void getErrors(std::vector* error_list) = 0; -}; - -class Statement : public AstNode { -public: - virtual std::string getNodeType() = 0; - virtual std::string toString() = 0; - virtual Symbol* buildSymbolTable(SymbolTable* table) = 0; - virtual void getErrors(std::vector* error_list) = 0; -}; - -class Expression : public AstNode { -public: - virtual std::string getNodeType() = 0; - virtual std::string toString() = 0; - virtual Symbol* buildSymbolTable(SymbolTable* table) = 0; - virtual void getErrors(std::vector* error_list) = 0; -}; - -class Var : public Expression { -public: - virtual std::string getNodeType() = 0; - virtual std::string toString() = 0; - virtual Symbol* buildSymbolTable(SymbolTable* table) = 0; - virtual void getErrors(std::vector* error_list) = 0; -}; - -class Variable : public Var { -public: - Token* _name; - Variable* _var; - - Variable(Token* name, Variable* var) : - _name(name), _var(var) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class VarType : public AstNode { -public: - virtual std::string getNodeType() = 0; - virtual std::string toString() = 0; - virtual Symbol* buildSymbolTable(SymbolTable* table) = 0; - virtual std::string toCastString() = 0; - virtual void getErrors(std::vector* error_list) = 0; -}; - -class BaseType : public VarType { -public: - Token* _type; - Token* _auto_name; - - BaseType(Token* type, Token* auto_name) : - _type(type), _auto_name(auto_name) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class CustomType : public VarType { -public: - Variable* _type; - - CustomType(Variable* type) : _type(type){} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class FuncType : public VarType { -public: - Token* _func; - std::vector* _param_types; - std::vector* _return_types; - - FuncType(Token* func, std::vector* param_types, std::vector* return_types) : - _func(func), _param_types(param_types), _return_types(return_types) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class ConstType : public VarType { -public: - VarType* _type; - - ConstType(VarType* type) : _type(type) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class PointerType : public VarType { -public: - VarType* _type; - - PointerType(VarType* type) : _type(type) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class ArrayType : public VarType { -public: - VarType* _type; - Expression* _array_length; - - ArrayType(VarType* type, Expression* array_length) : - _type(type), _array_length(array_length) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - std::string toCastString(); - void getErrors(std::vector* error_list); -}; - -class Parameter : public AstNode { -public: - Token* _id; - VarType* _type; - - Parameter(Token* id, VarType* type) : - _id(id), _type(type) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class Program : public AstNode { -public: - std::vector* _stmts; - - Program(std::vector* stmts) : _stmts(stmts) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class Macro : public Statement { -public: - Token* _macro; - - Macro(Token* macro) : _macro(macro) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class CompoundStmt : public Statement { -public: - std::vector* _stmts; - - CompoundStmt(std::vector* stmts) : _stmts(stmts) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class Declaration : public Statement { -public: - virtual std::string getNodeType() = 0; - virtual std::string toString() = 0; - virtual Symbol* buildSymbolTable(SymbolTable* table) = 0; - virtual void buildVTable(VTable*, SymbolTable*) = 0; - virtual void getErrors(std::vector* error_list) = 0; -}; - -class VarDec : public Declaration { -public: - Token* _id; - VarType* _type; - Expression* _expr; - - VarDec(Token* id, VarType* type, Expression* expr) : - _id(id), _type(type), _expr(expr) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class FuncDec : public Declaration { -public: - Token* _id; - std::vector* _params; - std::vector* _returns; - CompoundStmt* _body; - - FuncDec(Token* id, std::vector* params, std::vector* returns, CompoundStmt* body) : - _id(id), _params(params), _returns(returns), _body(body) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class CastFuncDec : public Declaration { -public: - VarType* _casting_type; - std::vector* _params; - std::vector* _returns; - CompoundStmt* _body; - - CastFuncDec(VarType* casting_type, std::vector* params, std::vector* returns, CompoundStmt* body) : - _casting_type(casting_type), _params(params), _returns(returns), _body(body) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class OpFuncDec : public Declaration { -public: - Token* _op; - std::vector* _params; - std::vector* _returns; - CompoundStmt* _body; - - OpFuncDec(Token* op, std::vector* params, std::vector* returns, CompoundStmt* body) : - _op(op), _params(params), _returns(returns), _body(body) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class EnumDec : public Declaration { -public: - Token* _start; - Token* _id; - VarType* _base_type; - std::vector* _declist; - - EnumDec(Token* start, Token* id, VarType* base_type, std::vector* declist) : - _start(start), _id(id), _base_type(base_type), _declist(declist) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class PackDec : public Declaration { -public: - Token* _start; - Token* _id; - VarType* _base_type; - std::vector* _declist; - - PackDec(Token* start, Token* id, VarType* base_type, std::vector* declist) : - _start(start), _id(id), _base_type(base_type), _declist(declist) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class VariantDec : public Declaration { -public: - Token* _start; - Token* _id; - std::vector* _declist; - - VariantDec(Token* start, Token* id, std::vector* declist) : - _start(start), _id(id), _declist(declist) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void buildVTable(VTable*, SymbolTable*); - void getErrors(std::vector* error_list); -}; - -class IfStmt : public Statement { -public: - Token* _start; - Expression* _cond; - CompoundStmt* _body; - Statement* _elseBody; //will either be if statement or compound statement - - IfStmt(Token* start, Expression* cond, CompoundStmt* body, Statement* elseBody) : - _start(start), _cond(cond), _body(body), _elseBody(elseBody) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class SwitchCase : public AstNode { -public: - Expression* _case; - CompoundStmt* _body; - - SwitchCase(Expression* c, CompoundStmt* body) : - _case(c), _body(body) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class SwitchStmt : public Statement { -public: - Token* _start; // don't need this since there isn't any errors at this level - Expression* _cond; - std::vector* _cases; - - SwitchStmt(Token* start, Expression* cond, std::vector* cases) : - _start(start), _cond(cond), _cases(cases) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class WhileStmt : public Statement { -public: - Token* _start; //dont need - Expression* _cond; - CompoundStmt* _body; - - WhileStmt(Token* start, Expression* cond, CompoundStmt* body) : - _start(start), _cond(cond), _body(body) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class ForStmt : public Statement { -public: - Token* _start; //dont need - Token* _id; - Expression* _iter; - Expression* _by; - CompoundStmt* _body; - - ForStmt(Token* start, Token* id, Expression* iter, Expression* by, CompoundStmt* body) : - _start(start), _id(id), _iter(iter), _by(by), _body(body) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class ExprStmt : public Statement { -public: - Expression* _expr; - - ExprStmt(Expression* expr) : _expr(expr) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class StopStmt : public Statement { -public: - Token* _token; - - StopStmt(Token* token) : _token(token) {} - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class BreakStmt : public Statement { -public: - Token* _token; - - BreakStmt(Token* token) : _token(token) {} - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class ContinueStmt : public Statement { -public: - Token* _token; - - ContinueStmt(Token* token) : _token(token) {} - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class MemberAccess : public Var { -public: - Var* _parent; - Token* _id; - - MemberAccess(Var* parent, Token* id) : _parent(parent), _id(id) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class ArrayAccess : public Var { -public: - Var* _parent; - Expression* _expr; - - ArrayAccess(Var* parent, Expression* expr) : _parent(parent), _expr(expr) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class Call : public Var { -public: - Var* _parent; - std::vector* _args; - - Call(Var* parent, std::vector* args) : - _parent(parent), _args(args) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class Assignment : public Expression { -public: - Token* _op; - Var* _var; - Expression* _expr; - - Assignment(Var* var, Token* op, Expression* expr) : - _var(var), _op(op), _expr(expr) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class BinaryExpr : public Expression { -public: - Token* _op; - Expression* _left; - Expression* _right; - - BinaryExpr(Token* op, Expression* left, Expression* right) : - _op(op), _left(left), _right(right) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class UnaryExpr : public Expression { -public: - Token* _op; - Expression* _expr; - - UnaryExpr(Token* op, Expression* expr) : _op(op), _expr(expr) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class Cast : public Expression { -public: - VarType* _type; - Expression* _expr; - - Cast(VarType* type, Expression* expr) : - _type(type), _expr(expr) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class IntValue : public Expression { -public: - Token* _value; - - IntValue(Token* value) : _value(value) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class HexValue : public Expression { -public: - Token* _value; - - HexValue(Token* value) : _value(value) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class BoolValue : public Expression { -public: - Token* _value; - - BoolValue(Token* value) : _value(value) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class FloatValue : public Expression { -public: - Token* _value; - - FloatValue(Token* value) : _value(value) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class StringValue : public Expression { -public: - Token* _value; - - StringValue(Token* value) : _value(value) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class ArrayValue : public Expression { -public: - std::vector* _elements; - - ArrayValue(std::vector* elements) : _elements(elements) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; - -class ObjectValue : public Expression { -public: - std::vector* _elements; - - ObjectValue(std::vector* elements) : _elements(elements) {} - - std::string getNodeType(); - std::string toString(); - Symbol* buildSymbolTable(SymbolTable* table); - void getErrors(std::vector* error_list); -}; diff --git a/src/compiler/errors.rs b/src/compiler/errors.rs new file mode 100644 index 0000000..f346669 --- /dev/null +++ b/src/compiler/errors.rs @@ -0,0 +1,185 @@ +use crate::compiler::CompilationUnit; +use super::lexer::Token; + +#[derive(Debug)] +pub enum Severity { + Hint, + Warning, + Error, +} + +impl Severity { + pub fn name(&self) -> String { + match self { + Severity::Hint => "Hint".to_string(), + Severity::Warning => "Warning".to_string(), + Severity::Error => "Error".to_string(), + } + } + + pub fn ansi_color_code(&self) -> String { + match self { + Severity::Hint => "94".to_string(), // Bright Blue + Severity::Warning => "33".to_string(), // Yellow + Severity::Error => "31".to_string(), // Red + } + } +} + +pub enum OceanError { + LexError(Severity, Token, String), + ParseError(Severity, String), +} + +pub fn display_error (compilation_unit: &CompilationUnit, error: &OceanError) { + match error { + OceanError::LexError(severity, token, message) => { + display_message(severity, message.to_string(), token.start, token.end, compilation_unit) + } + OceanError::ParseError(severity, message) => { + println!("Parse error :(") + } + } +} + +pub fn display_message ( + severity: &Severity, + message: String, + start_offset: usize, end_offset: usize, + compilation_unit: &CompilationUnit +) { + println!("{}: {}", severity.name(), message); + + let file_contents = compilation_unit.file_content.as_bytes(); + let file_name = &compilation_unit.filename; + + let line_spans = line_spans(file_contents); + + let mut line_index = 0; + let largest_line_number = line_spans.len(); + + let width = format!("{}", largest_line_number).len(); + + while line_index < line_spans.len() { + if start_offset >= line_spans[line_index].0 && start_offset <= line_spans[line_index].1 { + let column_index = start_offset - line_spans[line_index].0; + println!( + "{} \u{001b}[{}m{}:{}:{}\u{001b}[0m", + "-".repeat(width + 3), + severity.ansi_color_code(), + file_name, + line_index + 1, + column_index + 1 + ); + if line_index > 0 { + print_source_line( + &severity, + file_contents, + line_spans[line_index - 1], + start_offset, + end_offset, + line_index - 1, + largest_line_number, + ); + } + print_source_line( + &severity, + file_contents, + line_spans[line_index], + start_offset, + end_offset, + line_index, + largest_line_number, + ); + + print!( + "{}", + " ".repeat(start_offset - line_spans[line_index].0 + width + 4) + ); + println!( + "\u{001b}[{}m^- {}\u{001b}[0m", + severity.ansi_color_code(), + message + ); + + while line_index < line_spans.len() && end_offset > line_spans[line_index].0 { + line_index += 1; + if line_index >= line_spans.len() { + break; + } + print_source_line( + &severity, + file_contents, + line_spans[line_index], + start_offset, + end_offset, + line_index, + largest_line_number, + ); + } + + break; + } else { + line_index += 1 + } + } + + println!("\u{001b}[0m{}", "-".repeat(width + 3)); +} + +fn print_source_line( + severity: &Severity, + file_contents: &[u8], + file_span: (usize, usize), + start_offset: usize, + end_offset: usize, + line_number: usize, + largest_line_number: usize, +) { + let mut index = file_span.0; + + let width = format!("{}", largest_line_number).len(); + + print!(" {:= start_offset && index < end_offset) + || (start_offset == end_offset && index == start_offset) + { + // In the error span + print!("\u{001b}[{}m{}", severity.ansi_color_code(), c as char) + } else { + print!("\u{001b}[0m{}", c as char) + } + index += 1; + } + + println!(); +} + +fn line_spans(contents: &[u8]) -> Vec<(usize, usize)> { + let mut idx = 0; + let mut output = vec![]; + + let mut start = idx; + while idx < contents.len() { + if contents[idx] == b'\n' { + output.push((start, idx)); + start = idx + 1; + } + idx += 1; + } + if start < idx { + output.push((start, idx)); + } + + output +} diff --git a/src/compiler/lexer.rs b/src/compiler/lexer.rs new file mode 100644 index 0000000..b0cc3a8 --- /dev/null +++ b/src/compiler/lexer.rs @@ -0,0 +1,310 @@ +use super::errors::*; + +#[derive(Clone, Debug, PartialEq)] +pub enum TokenType { + EndOfInput, + Error, + Comment, + Macro, + String, + InterpolatedString, + Number, + Type, + Identifier, + LParen, + RParen, + LSquare, + RSquare, + LCurly, + RCurly, + Keyword, + Symbol, + Dot, + Comma, + Colon, + Arrow, + Underscore, + SemiColon +} + +#[derive(Clone)] +pub struct Token { + pub token_type: TokenType, + pub lexeme: String, + pub start: usize, + pub end: usize +} + +impl Token { + pub fn new(token_type: TokenType, lexeme: String, start: usize, end: usize) -> Token { + Token {token_type, lexeme, start, end} + } + + pub fn print(&self) { + print!("<[{:?}] '{}' {} {}>", self.token_type, self.lexeme, self.start, self.end); + } +} + +pub struct TokenStack { + token_vec: Vec, + index: usize +} + +impl TokenStack { + pub fn push(&mut self, token: Token) { + self.token_vec.push(token); + } + + pub fn peek(&self) -> Token { + if self.index >= self.token_vec.len() { + Token::new(TokenType::EndOfInput, "EOI".to_string(),usize::MAX, usize::MAX) + } else { + self.token_vec[self.index].clone() + } + } + + pub fn consume(&mut self) -> Token { + let t = if self.index >= self.token_vec.len() { + Token::new(TokenType::EndOfInput, "EOI".to_string(), usize::MAX, usize::MAX) + } else { + self.token_vec[self.index].clone() + }; + self.index += 1; + t + } + + pub fn is_empty(&self) -> bool { + self.token_vec.len() == self.index + } + + pub fn iterable(&self) -> Vec { + self.token_vec[self.index..self.token_vec.len()].to_vec() + } + + pub fn new() -> TokenStack { + TokenStack { token_vec: Vec::new(), index: 0 } + } +} + +pub fn lex(input: String) -> (TokenStack, Vec) { + let input_length = input.len(); + let input_chars: Vec<_> = input.chars().collect(); // I understand both chars and this collect is not great but I am learning :) + let mut lexeme = String::new(); //we probably don't need this here :/ + let mut index = 0; + let mut tokens = TokenStack::new(); + let mut errors = Vec::new(); + while index < input_length { + let start_index = index; + let c = input_chars[index]; + match c { + 'A'..='Z' | 'a'..='z' | '_' => { + index += 1; + lexeme.push_str(&c.to_string()); + while index < input_length { + let n = input_chars[index]; + match n { + 'A'..='Z' | 'a'..='z' | '0'..='9' | '_' => lexeme.push_str(&n.to_string()), + _ => { + index -= 1; + break; + } + } + index += 1; + } + + //check against every other thing it could be + match lexeme.as_str() { + "_" => tokens.push(Token::new(TokenType::Underscore, lexeme.clone(), start_index, index)), + "i8" | "i16" | "i32" | "i64" | "f32" | "f64" | + "u8" | "u16" | "u32" | "u64" | "string" | "auto" | + "bool" | "func" | "void" | "ref" | "lazy" | + "optional" | "comp" => { + tokens.push(Token::new(TokenType::Type, lexeme.clone(), start_index, index)); + } + "if" | "else" | "return" | "continue" | + "break" | "loop" | "enum" | "pack" | + "switch" | "default" | "let" | "cast" | + "for" | "in" | "as" | "use" => { + tokens.push(Token::new(TokenType::Keyword, lexeme.clone(), start_index, index)); + } + _ => { + tokens.push(Token::new(TokenType::Identifier, lexeme.clone(), start_index, index)); + } + } + + lexeme.clear(); + }, + '0'..='9' => { + lexeme.push_str(&c.to_string()); + index += 1; + let mut decimal = false; + while index < input_length { + let n = input_chars[index]; + match n { + '0'..='9' => lexeme.push_str(&n.to_string()), + '.' => { + if decimal { + index -= 1; + break; + } + lexeme.push_str(&n.to_string()); + decimal = true; + } + _ => { + index -= 1; + break; + } + } + index += 1 + } + + tokens.push(Token::new(TokenType::Number, lexeme.clone(), start_index, index)); + lexeme.clear(); + }, + '\"' | '\'' | '`' => { + let delim = c; + index += 1; + let mut found_end = false; + while index < input_length { + let n = input_chars[index]; + match n { + '\'' => if delim == '\'' { + found_end = true; + index += 1; + break + } + else + { + lexeme.push_str(&n.to_string()) + }, + '\"' => if delim == '\"' { + found_end = true; + index += 1; + break + } + else + { + lexeme.push_str(&n.to_string()) + }, + '`' => if delim == '`' { + found_end = true; + index += 1; + break + } + else + { + lexeme.push_str(&n.to_string()) + }, + '\\' => { + if index == input_length - 1 { + lexeme.push_str(&n.to_string()); + } else { + index += 1; + let x = input_chars[index]; + match x { + 'n' => lexeme.push_str(&"\n".to_string()), + 'r' => lexeme.push_str(&"\r".to_string()), + 't' => lexeme.push_str(&"\t".to_string()), + //need to add excape characters for octal, hex, and unicode + _ => lexeme.push_str(&x.to_string()) + } + } + } + _ => lexeme.push_str(&n.to_string()) + } + index += 1; + } + + if !found_end { + errors.push(OceanError::LexError( + Severity::Error, + Token::new(TokenType::String, lexeme.clone(), start_index, index), + "Unending string".to_string() + )) + } else if (delim == '`') { + tokens.push(Token::new(TokenType::InterpolatedString, lexeme.clone(), start_index, index)) + } else { + tokens.push(Token::new(TokenType::String, lexeme.clone(), start_index, index)); + } + lexeme.clear(); + } + '#' => { + index += 1; + while index < input_length { + let n = input_chars[index]; + match n { + '\n' => { + index -= 1; + break; + } + _ => lexeme.push_str(&n.to_string()) + } + index += 1; + } + tokens.push(Token::new(TokenType::Comment, lexeme.clone(), start_index, index)); + lexeme.clear(); + }, + '@' => { + index += 1; + while index < input_length { + let n = input_chars[index]; + match n { + '\n' => { + index -= 1; + break; + } + _ => lexeme.push_str(&n.to_string()) + } + index += 1; + } + tokens.push(Token::new(TokenType::Macro, lexeme.clone(), start_index, index)); + lexeme.clear(); + }, + ':' | '>' | '<' | '?' | '.' | '/' | ';' | + '~' | '!' | '$' | '%' | '&' | '^' | '*' | + '-' | '+' | '=' | '|' | '\\'| ',' => { + let start = index; + index += 1; + lexeme.push_str(&c.to_string()); + while index < start + 3 && index < input_length { + let n = input_chars[index]; + match n { + ':' | '>' | '<' | '?' | '.' | '/' | ';' | + '~' | '!' | '$' | '%' | '&' | '^' | '*' | + '-' | '+' | '=' | '|' | '\\'| ',' => lexeme.push_str(&n.to_string()), + _ => { + index -= 1; + break; + } + } + index += 1; + } + + //check all the other things it could be + match lexeme.as_str() { + "." => tokens.push(Token::new(TokenType::Dot, lexeme.clone(), start_index, index)), + "," => tokens.push(Token::new(TokenType::Comma, lexeme.clone(), start_index, index)), + ":" => tokens.push(Token::new(TokenType::Colon, lexeme.clone(), start_index, index)), + "->" => tokens.push(Token::new(TokenType::Arrow, lexeme.clone(), start_index, index)), + ";" => tokens.push(Token::new(TokenType::SemiColon, lexeme.clone(), start_index, index)), + _ => tokens.push(Token::new(TokenType::Symbol, lexeme.clone(), start_index, index)) + } + + lexeme.clear(); + }, + '(' => tokens.push(Token::new(TokenType::LParen, "(".to_string(), start_index, index)), + ')' => tokens.push(Token::new(TokenType::RParen, ")".to_string(), start_index, index)), + '[' => tokens.push(Token::new(TokenType::LSquare, "[".to_string(), start_index, index)), + ']' => tokens.push(Token::new(TokenType::RSquare, "]".to_string(), start_index, index)), + '{' => tokens.push(Token::new(TokenType::LCurly, "{".to_string(), start_index, index)), + '}' => tokens.push(Token::new(TokenType::RCurly, "}".to_string(), start_index, index)), + ' ' | '\t' | '\r' | '\n' => {}, + _ => errors.push(OceanError::LexError( + Severity::Error, + Token::new(TokenType::Error, c.to_string(), start_index, index), + "Unrecognized token".to_string())) + } + index += 1; + } + (tokens, errors) +} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs new file mode 100644 index 0000000..10a1f21 --- /dev/null +++ b/src/compiler/mod.rs @@ -0,0 +1,58 @@ +pub mod lexer; +pub mod parser; +pub mod errors; + +use self::lexer::*; +use self::errors::*; + +pub struct CompilationUnit { + filename: String, + file_content: String, + //subunits: Vec, + tokens: TokenStack, + // ast + // symbol table + errors: Vec, +} + +impl CompilationUnit { + pub fn new(filename: String, file_content: String) -> CompilationUnit { + CompilationUnit { + filename, + file_content, + tokens: TokenStack::new(), + errors: Vec::new() + } + } + + pub fn compile(&mut self) { + println!("{}", self.filename); + // Lexical pass + (self.tokens, self.errors) = lex(self.file_content.clone()); + if !self.errors.is_empty() { + self.print_errors(); + return; + } + + // Parser pass + //(self.ast, self.errors) = parse(self.tokens); + if !self.errors.is_empty() { + self.print_errors(); + return; + } + + // extra passes + println!("Good :)"); + } + + pub fn print_errors(&self) { + for error in &self.errors { + display_error(self, error); + } + } +} + +pub fn compile(filename: String, file_content: String) { + let mut main = CompilationUnit::new(filename, file_content); + main.compile(); +} \ No newline at end of file diff --git a/src/compiler/parser/ast.rs b/src/compiler/parser/ast.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/compiler/parser/mod.rs b/src/compiler/parser/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/helper.hpp b/src/helper.hpp deleted file mode 100644 index 1293628..0000000 --- a/src/helper.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -//so we don't go including these everywhere when we don't want to print messages -#ifdef DEBUG_MESSAGES -#include -#include -#include -#endif - -template -inline void debug(T message) { -#ifdef DEBUG_MESSAGES - std::cout << message << std::endl; -#endif -} - -inline void debugl() { - std::cout << std::endl; -} - -template -inline void debugl(T curr, Types... next) { -#ifdef DEBUG_MESSAGES - std::cout << curr; - - debugl(next...); -#endif -} - -template -inline void tdebug(T message) { -#if defined DEBUG_TOKENS and defined DEBUG_MESSAGES - std::cout << message << std::endl; -#endif -} - -inline void tdebugf(const char* format...) { -#if defined DEBUG_TOKENS and defined DEBUG_MESSAGES - va_list argptr; - va_start(argptr, format); - - vprintf(format, argptr); - - va_end(argptr); -#endif -} - -template -inline void adebug(T message) { -#if defined DEBUG_AST and defined DEBUG_MESSAGES - std::cout << message << std::endl; -#endif -} - -inline void adebugf(const char* format...) { -#if defined DEBUG_AST and defined DEBUG_MESSAGES - va_list argptr; - va_start(argptr, format); - - vprintf(format, argptr); - - va_end(argptr); -#endif -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6b46e6f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod compiler; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 16c954d..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include - -#include "helper.hpp" - -#include "ast.hpp" - -#include "ocean.tab.hpp" - -extern FILE* yyin; -Program* root; - -int main(int argc, char** argv) { - ++argv, --argc; //skip over the program name - if(argc > 0){ - yyin = fopen(argv[0], "r"); - if(yyin == nullptr) - { - std::cout << "The file '" << argv[0] << "' was not able to be opened" << std::endl; - return 1; - } - }else{ - std::cout << "Please supply a source file." << std::endl; - return 1; - } - - yyparse(); - debug("Done Parsing..."); - if(root == nullptr){ - std::cout << "There was an issue with parsing this file. The parser returned a null ast root." << std::endl; - return 1; - } else { - adebug(root->toString()); - } - - debug("This file contained valid ocean source code"); - Program* main_root = root; //save the main root node of the ast so it doesn't get messed up by parsing other files - SymbolTable* table = new SymbolTable(nullptr, "global"); - auto final_type = main_root->buildSymbolTable(table); - - if(final_type->type == SymType::Error) { - auto error_list = new std::vector(); - main_root->getErrors(error_list); - std::cout << "There were " << error_list->size() << " errors :(" << std::endl; - for (auto error : *error_list) { - std::cout << error << std::endl; - } - } else { - std::cout << "There were no type checking errors!" << std::endl; - } - - return 0; -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..df45683 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,16 @@ +mod compiler; +use compiler::{compile}; + +use std::env; +use std::fs::File; +use std::io::prelude::*; + +fn main() -> std::io::Result<()> { + let args: Vec = env::args().collect(); + let source = &args[1]; + let mut file = File::open(source)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + compile(source.to_string(), contents.to_string()); + Ok(()) +} diff --git a/src/ocean.l b/src/ocean.l deleted file mode 100644 index 8792453..0000000 --- a/src/ocean.l +++ /dev/null @@ -1,209 +0,0 @@ -%{ -#include -#include -#include - -#include "type_helper.hpp" -#include "helper.hpp" - -#include -#include -#include "token.hpp" -#include "ast.hpp" - -#include "ocean.tab.hpp" - -#define ARRAY 258 -#define yyterminate() return ENDOFFILE - -//typedef union YYSTYPE YYSTYPE; -//extern YYSTYPE yylval; //passes the value to parser -extern "C" int yylex(); - -int line_number = 1; -int column_number = 1; -int next_line_number = 1; -int next_column_number = 1; - -void UpdateLineColumnNumber(); -void Drop(); -void Drop(const char* message); -void InvalidToken(); -int ProcessToken(const char* name, int token_parser_id, TokenType token_type, int value_type); -%} - -/* Rules Section */ -%% - - /******* KEYWORDS *********/ -"bool" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } -"byte" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } -"i16"|"i32"|"i64" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } -"s16"|"s32"|"s64" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } -"u16"|"u32"|"u64" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } -"f32"|"f64"|"f128" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } -"string" { return ProcessToken("Type", TYPE, TokenType::Type, 0); } - -"auto" { return ProcessToken("auto", AUTO, TokenType::Auto, 0); } -"func" { return ProcessToken("func", FUNC, TokenType::Func, 0); } -"op" { return ProcessToken("op", OP, TokenType::Op, 0); } -"cast" { return ProcessToken("cast", CAST, TokenType::Cast, 0); } - -"const" { return ProcessToken("const", CONST, TokenType::Const, 0); } -"enum" { return ProcessToken("enum", ENUM, TokenType::Enum, 0); } -"pack" { return ProcessToken("pack", PACK, TokenType::Pack, 0); } -"variant" { return ProcessToken("variant", VARIANT, TokenType::Variant, 0); } - -"default" { return ProcessToken("DEFAULT", DEFAULT, TokenType::Default, 0); } -"stop" { return ProcessToken("STOP", STOP, TokenType::Stop, 0); } -"break" { return ProcessToken("BREAK", BREAK, TokenType::Break, 0); } -"continue" { return ProcessToken("CONTINUE", CONTINUE, TokenType::Continue, 0); } -"if" { return ProcessToken("IF", IF, TokenType::If, 0); } -"else" { return ProcessToken("ELSE", ELSE, TokenType::Else, 0); } -"while" { return ProcessToken("WHILE", WHILE, TokenType::While, 0); } -"for" { return ProcessToken("FOR", FOR, TokenType::For, 0); } -"in" { return ProcessToken("IN", IN, TokenType::In, 0); } -"by" { return ProcessToken("BY", BY, TokenType::By, 0); } -"switch" { return ProcessToken("SWITCH", SWITCH, TokenType::Switch, 0); } - - - /******* WHITESPACE ********/ -"\n" { - return ProcessToken("NEWLINE", NEWLINE, TokenType::Newline, 0); -} - -[ \t\r\v\f] { - Drop("WHITESPACE"); -}; - - /******** MACRO / COMMENTS ********/ -\@.*$ { return ProcessToken("MACRO", MACRO, TokenType::Macro, 0); } -\{("asm"|"ast")?\@[^\@]*\@+(?:[^\@\}][^\@]*\@+)*\} { return ProcessToken("MACRO", MACRO, TokenType::Macro, 0); } - -"#".*$ { Drop(); } //just drop comments //return ProcessToken("COMMENT", COMMENT, 0); } -\{\#[^\#]*\#+(?:[^\#\}][^\#]*\#+)*\} { Drop(); } //just drop comments - - /******* OPERATORS/ OTHER SYMBOLS ********/ -"+="|"-="|"*="|"/="|"%="|"&="|"|="|"^="|"<<="|">>=" { - return ProcessToken("OPASSIGN", ASSIGN, TokenType::OpAssign, 0); } -">>"|"<<" { return ProcessToken("SHIFT", SHIFT, TokenType::Shift, 0); } -"?" { return ProcessToken("QUESTION", QUESTION, TokenType::Question, 0); } -"=="|"!=" { return ProcessToken("EQUIV", EQUIV, TokenType::EqOp, 0); } -"<="|">=" { return ProcessToken("RELAT", RELAT, TokenType::RelOp, 0); } -"&&"|"||"|"^^" { return ProcessToken("LOGIC", LOGIC, TokenType::LogOp, 0); } -"&"|"|"|"^" { return ProcessToken("BITWISE", BITWISE, TokenType::BitOp, 0); } -"+"|"-" { return ProcessToken("ADD", ADD, TokenType::AddOp, 0); } -"*"|"/"|"%" { return ProcessToken("MULT", MULT, TokenType::MultOp, 0); } -"->" { return ProcessToken("ARROW", ARROW, TokenType::Apply, 0); } -"!" { return ProcessToken("NOT", NOT, TokenType::Not, 0); } -"." { return ProcessToken("DOT", DOT, TokenType::Access, 0); } -"..." { return ProcessToken("RANGE", RANGE, TokenType::Range, 0); } -"," { return ProcessToken("COMMA", COMMA, TokenType::Comma, 0); } -"=" { return ProcessToken("ASSIGN", ASSIGN, TokenType::Equal, 0); } -";" { return ProcessToken("SEMICOLON", SEMICOLON, TokenType::Semicolon, 0); } -"::" { return ProcessToken("DUB_COLON", DUBCOLON, TokenType::DubColon, 0); } -"~" { return ProcessToken("TILDE", TILDE, TokenType::Tilde, 0); } -":" { return ProcessToken("COLON", COLON, TokenType::Colon, 0); } - - /******* BRACKETS *******/ -"(" { return ProcessToken("PAREN_OPEN", PAREN_OPEN, TokenType::LeftParen, 0); } -")" { return ProcessToken("PAREN_CLOSED", PAREN_CLOSED, TokenType::RightParen, 0); } -"[" { return ProcessToken("SQUARE_OPEN", SQUARE_OPEN, TokenType::LeftSquare, 0); } -"]" { return ProcessToken("SQUARE_CLOSED", SQUARE_CLOSED, TokenType::RightSquare, 0); } -"{" { return ProcessToken("BRACE_OPEN", BRACE_OPEN, TokenType::LeftBrace, 0); } -"}" { return ProcessToken("BRACE_CLOSED", BRACE_CLOSED, TokenType::RightBrace, 0); } -"<" { return ProcessToken("ANGLE_OPEN", ANGLE_OPEN, TokenType::LeftAngle, 0); } -">" { return ProcessToken("ANGLE_CLOSED", ANGLE_CLOSED, TokenType::RightAngle, 0); } - - - /******** VALUES **********/ -"true"|"false" { return ProcessToken("BOOLVAL", BOOLVAL, TokenType::Boolean, 3); } -"0x"[0-9A-F]+ { return ProcessToken("HEXVAL", HEXVAL, TokenType::HexCode, 4); } -[0-9]+ { return ProcessToken("INTVAL", INTVAL, TokenType::Integer, 1); } -([0-9]*\.[0-9]+|[0-9]+\.[0-9]+) { return ProcessToken("FLOATVAL", FLOATVAL, TokenType::Float, 2); } - - /*add escaped quotes*/ -\$?(\"[^\"]*\"|\'[^\']*\') { return ProcessToken("STRINGVAL", STRINGVAL, TokenType::String, 0); } -[a-zA-Z_][a-zA-Z0-9_]* { return ProcessToken("IDENTIFIER", IDENTIFIER, TokenType::Identifier, 0); } - -. { - //tdebugf("[%i, %i] Unknown Token %s\n", line_number, column_number, yytext); - - //column_number += yyleng; - InvalidToken(); - exit(0); - - //maybe we want to create a token for this unknown token and - //then store it in a list so we can report all of the unknown tokens at once - //yylval.lexeme = strdup(yytext); - //return UNKNOWN; -} -%% - -int yywrap(void){ - return 1; -} - -void InvalidToken(){ - fprintf(stderr, "ERROR ON LINE %i [%i] : \n Unknown Token %s\n", line_number, column_number, yytext); -} - -void Drop() -{ - UpdateLineColumnNumber(); - tdebugf("[%i, %i] DROPPED : %s\n", line_number, column_number, yytext); -} - -void Drop(const char* message) -{ - UpdateLineColumnNumber(); - tdebugf("[%i, %i] DROPPED : %s\n", line_number, column_number, message); -} - -int ProcessToken(const char* name, int token_parser_id, TokenType token_type, int value_type) -{ - UpdateLineColumnNumber(); - - tdebugf("[%i, %i] %s %s\n", line_number, column_number, name, yytext); - - Token* token; - if(value_type == 0){ - token = new Token(token_type, strdup(yytext), line_number, column_number); - }else if(value_type == 1){ - token = new Token(token_type, (u_64)strtoull(yytext, nullptr, 10), line_number, column_number); - }else if(value_type == 2){ - token = new Token(token_type, (f_128)strtold(yytext, nullptr), line_number, column_number); - }else if(value_type == 3){ - token = new Token(token_type, strcmp(yytext, "true") == 0, line_number, column_number); - }else if(value_type == 4) { //hex value - token = new Token(token_type, strdup(yytext) + 2, line_number, column_number); - } - - yylval.token = token; - return token_parser_id; -} - -void UpdateLineColumnNumber() -{ - line_number = next_line_number; - column_number = next_column_number; - - int off = 1; - int reset = 0; - for(int i = 0; i < yyleng; i++) - { - if(yytext[i] == '\n') { - next_line_number = next_line_number + 1; - reset = 1; - off = 1; - } else { - off = off + 1; - } - } - next_column_number = reset ? off : next_column_number + off - 1; -} - -void yyerror(const char* s){ - fprintf(stderr, "\nERROR ON LINE %i [%i] : \n %s\n", line_number, column_number, s); - exit(0); -} diff --git a/src/ocean.y b/src/ocean.y deleted file mode 100644 index b7ff24f..0000000 --- a/src/ocean.y +++ /dev/null @@ -1,347 +0,0 @@ -%{ -#include -#include -#include - -#include "token.hpp" -#include "ast.hpp" - -extern void yyerror(const char* s); -extern "C" int yylex(); - -//extern "C" void macro_start(char* in); - -extern FILE* yyin; -extern char* yytext; -extern int line_number; -extern int column_number; - -extern Program* root; - -%} - -%locations -%define parse.error verbose - -%union { - Token* token; - Program* program; - Statement* statement; - Parameter* parameter; - Expression* expression; - VarType* vartype; - Var* var; - Variable* nvar; - Declaration* declaration; - CompoundStmt* compound; - - std::vector* stmtlist; - std::vector* switchcaselist; - std::vector* paramlist; - std::vector* declist; - std::vector* arglist; - std::vector* typelist; -} - -%token ENDOFFILE 0 "end of file" -%token TYPE AUTO FUNC OP CAST -%token ENUM PACK VARIANT -%token STOP BREAK CONTINUE IF ELSE WHILE FOR IN BY -%token SWITCH RANGE DEFAULT - -%token QUESTION TILDE NEWLINE CONST -%token ARROW DOT NOT COMMA COLON SEMICOLON DUBCOLON -%token PAREN_OPEN PAREN_CLOSED -%token SQUARE_OPEN SQUARE_CLOSED -%token BRACE_OPEN BRACE_CLOSED -%token ANGLE_OPEN ANGLE_CLOSED -%token BOOLVAL -%token INTVAL -%token HEXVAL -%token FLOATVAL -%token STRINGVAL -%token IDENTIFIER - -%token MACRO - -%token SHIFT -%token EQUIV -%token RELAT -%token BITWISE -%token LOGIC -%token ADD -%token MULT - -%token ASSIGN - -%type PROG -%type STMT_LIST -%type STMT IFSTMT FELSE SWITCHSTMT WHILELOOP FORLOOP ASSIGNMENT -%type SWITCHCASELIST SWITCHBODY -%type DEC_LIST FDEC ENUM_LIST FENUM OBJARGS FOBJARGS -%type PARAMS FPARAMS -%type PARAM -%type EXPR BITWISER EQUIVALENCE COMPARATIVE SHIFTER ADDITIVE MULTIPLICATIVE RANGER UNARY PRIMARY POSTFIX ARRAYVAL CASTEXPR -%type VARTYPE -%type VAR -%type NVAR -%type ARGS FARGS -%type DEC -%type CMPD -%type TYPE_LIST -%type OPERATOR - -%% - -PROG : STMT_LIST { $$ = new Program($1); root = $$; } - | ENDOFFILE { $$ = new Program(new std::vector()); root = $$; } - ; - -STMT_LIST : STMT_LIST NEWLINE { $$ = $1; } - | STMT_LIST STMT LINEEND { $$ = $1; $$->push_back($2); } - | STMT_LIST error NEWLINE { $$ = $1; yyclearin; } - | NEWLINE { $$ = new std::vector(); } - | STMT LINEEND { $$ = new std::vector(); $$->push_back($1); } - | error NEWLINE { $$ = new std::vector(); yyclearin; } - ; - -LINEEND : NEWLINE - | ENDOFFILE - ; - -STMT : MACRO { $$ = new Macro($1); } - | DEC { $$ = $1; } - | IFSTMT { $$ = $1; } - | SWITCHSTMT { $$ = $1; } - | WHILELOOP { $$ = $1; } - | FORLOOP { $$ = $1; } - | ASSIGNMENT { $$ = $1; } - | CMPD { $$ = $1; } - | STOP { $$ = new StopStmt($1); } - | BREAK { $$ = new BreakStmt($1); } - | CONTINUE { $$ = new ContinueStmt($1); } - ; - -SWITCHSTMT : SWITCH EXPR SWITCHBODY { $$ = new SwitchStmt($1, $2, $3); } - ; - -SWITCHBODY : BRACE_OPEN SWITCHCASELIST BRACE_CLOSED { $$ = $2; } - ; - -SWITCHCASELIST : SWITCHCASELIST EXPR ARROW CMPD { - $$ = $1; - SwitchCase* switchCase = new SwitchCase($2, $4); - $$->push_back(switchCase); - } - | SWITCHCASELIST DEFAULT ARROW CMPD { - $$ = $1; - SwitchCase* switchCase = new SwitchCase(nullptr, $4); - $$->push_back(switchCase); - } - | SWITCHCASELIST NEWLINE { $$ = $1; } - | { $$ = new std::vector(); } - ; - -IFSTMT : IF EXPR CMPD FELSE { $$ = new IfStmt($1, $2, $3, $4); } - ; - -FELSE : ELSE CMPD { $$ = $2; } - | ELSE IFSTMT { $$ = $2; } - | { $$ = nullptr; } - ; - -WHILELOOP : WHILE EXPR CMPD { $$ = new WhileStmt($1, $2, $3); } - ; - -FORLOOP : FOR IDENTIFIER IN EXPR CMPD { $$ = new ForStmt($1, $2, $4, nullptr, $5); } - | FOR IDENTIFIER IN EXPR BY EXPR CMPD { $$ = new ForStmt($1, $2, $4, $6, $7); } - ; - -CMPD : BRACE_OPEN STMT_LIST BRACE_CLOSED { $$ = new CompoundStmt($2); } - ; - -DEC : IDENTIFIER COLON VARTYPE { $$ = new VarDec($1, $3, nullptr); } - | IDENTIFIER COLON VARTYPE ASSIGN EXPR { $$ = new VarDec($1, $3, $5); } - | IDENTIFIER COLON PAREN_OPEN PARAMS PAREN_CLOSED ARROW PAREN_OPEN PARAMS PAREN_CLOSED CMPD { - $$ = new FuncDec($1, $4, $8, $10); - } - | OP ANGLE_OPEN OPERATOR ANGLE_CLOSED COLON PAREN_OPEN PARAMS PAREN_CLOSED ARROW PAREN_OPEN PARAMS PAREN_CLOSED CMPD { - $$ = new OpFuncDec($3, $7, $11, $13); - } - | CAST ANGLE_OPEN VARTYPE ANGLE_CLOSED COLON PAREN_OPEN PARAMS PAREN_CLOSED ARROW PAREN_OPEN PARAMS PAREN_CLOSED CMPD { - $$ = new CastFuncDec($3, $7, $11, $13); //this is a little goofy but I can't think of a better way to do it cause we want to maintain the ability to search up the type - } - | ENUM IDENTIFIER VARTYPE FENUM { $$ = new EnumDec($1, $2, $3, $4); } - | PACK IDENTIFIER VARTYPE FDEC { $$ = new PackDec($1, $2, $3, $4); } - | VARIANT IDENTIFIER FDEC { $$ = new VariantDec($1, $2, $3); } - ; - -FDEC : BRACE_OPEN DEC_LIST BRACE_CLOSED { $$ = $2; } - ; - -DEC_LIST : DEC_LIST COMMA DEC { $$ = $1; $$->push_back($3); } - | DEC_LIST NEWLINE DEC { $$ = $1; $$->push_back($3); } - | DEC_LIST NEWLINE { $$ = $1; } - | NEWLINE DEC { $$ = new std::vector(); $$->push_back($2); } - | DEC { $$ = new std::vector(); $$->push_back($1); } - ; - -FENUM : BRACE_OPEN ENUM_LIST BRACE_CLOSED { $$ = $2; } - ; - -ENUM_LIST : ENUM_LIST COMMA IDENTIFIER COLON EXPR { $$ = $1; $$->push_back(new VarDec($3, nullptr, $5)); } - | ENUM_LIST NEWLINE IDENTIFIER COLON EXPR { $$ = $1; $$->push_back(new VarDec($3, nullptr, $5)); } - | ENUM_LIST COMMA IDENTIFIER { $$ = $1; $$->push_back(new VarDec($3, nullptr, nullptr)); } - | ENUM_LIST NEWLINE IDENTIFIER { $$ = $1; $$->push_back(new VarDec($3, nullptr, nullptr)); } - | ENUM_LIST NEWLINE { $$ = $1; } - | IDENTIFIER COLON EXPR { - $$ = new std::vector(); - $$->push_back(new VarDec($1, nullptr, $3)); - } - | IDENTIFIER { - $$ = new std::vector(); - $$->push_back(new VarDec($1, nullptr, nullptr)); - } - | NEWLINE IDENTIFIER COLON EXPR { - $$ = new std::vector(); - $$->push_back(new VarDec($2, nullptr, $4)); - } - | NEWLINE IDENTIFIER { - $$ = new std::vector(); - $$->push_back(new VarDec($2, nullptr, nullptr)); - } - ; - -PARAMS : FPARAMS { $$ = $1; } - | { $$ = new std::vector(); } - ; - -FPARAMS : FPARAMS COMMA PARAM { $$ = $1; $$->push_back($3); } - | PARAM { $$ = new std::vector(); $$->push_back($1); } - ; - -PARAM : IDENTIFIER COLON VARTYPE { $$ = new Parameter($1, $3); } - ; - -OPERATOR : LOGIC { $$ = $1; } - | BITWISE { $$ = $1; } - | EQUIV { $$ = $1; } - | RELAT { $$ = $1; } - | ANGLE_OPEN { $$ = $1; } - | ANGLE_CLOSED { $$ = $1; } - | SHIFT { $$ = $1; } - | ADD { $$ = $1; } - | MULT { $$ = $1; } - | RANGE { $$ = $1; } - | NOT { $$ = $1; } - | QUESTION { $$ = $1; } - | TILDE { $$ = $1; } - ; - -ASSIGNMENT : VAR ASSIGN EXPR { $$ = new ExprStmt(new Assignment($1, $2, $3)); } - | EXPR { $$ = new ExprStmt($1); } - ; - -EXPR : BITWISER LOGIC EXPR { $$ = new BinaryExpr($2, $1, $3); } - | BITWISER { $$ = $1; } - ; - -BITWISER : BITWISER BITWISE EQUIVALENCE { $$ = new BinaryExpr($2, $1, $3); } - | EQUIVALENCE { $$ = $1; } - ; - -EQUIVALENCE : EQUIVALENCE EQUIV COMPARATIVE { $$ = new BinaryExpr($2, $1, $3); } - | COMPARATIVE { $$ = $1; } - ; - -COMPARATIVE : COMPARATIVE RELAT SHIFTER { $$ = new BinaryExpr($2, $1, $3); } - | COMPARATIVE ANGLE_OPEN SHIFTER { $$ = new BinaryExpr($2, $1, $3); } - | COMPARATIVE ANGLE_CLOSED SHIFTER { $$ = new BinaryExpr($2, $1, $3); } - | SHIFTER { $$ = $1; } - ; - -SHIFTER : SHIFTER SHIFT ADDITIVE { $$ = new BinaryExpr($2, $1, $3); } - | ADDITIVE { $$ = $1; } - ; - -ADDITIVE : ADDITIVE ADD MULTIPLICATIVE { $$ = new BinaryExpr($2, $1, $3); } - | MULTIPLICATIVE { $$ = $1; } - ; - -MULTIPLICATIVE : MULTIPLICATIVE MULT RANGER { $$ = new BinaryExpr($2, $1, $3); } - | RANGER { $$ = $1; } - ; - -RANGER : RANGER RANGE UNARY { $$ = new BinaryExpr($2, $1, $3); } - | UNARY { $$ = $1; } - ; - -UNARY : NOT UNARY { $$ = new UnaryExpr($1, $2); } - | ADD UNARY { $$ = new UnaryExpr($1, $2); } - | TILDE UNARY { $$ = new UnaryExpr($1, $2); } - | POSTFIX { $$ = $1; } - ; - -POSTFIX : POSTFIX QUESTION { $$ = new UnaryExpr($2, $1); } - | CASTEXPR { $$ = $1; } - ; - -CASTEXPR : ANGLE_OPEN VARTYPE ANGLE_CLOSED PRIMARY { $$ = new Cast($2, $4); } - | PRIMARY { $$ = $1; } - ; - -PRIMARY : VAR { $$ = $1; } - | PAREN_OPEN EXPR PAREN_CLOSED { $$ = $2; } - | INTVAL { $$ = new IntValue($1); } - | HEXVAL { $$ = new HexValue($1); } - | BOOLVAL { $$ = new BoolValue($1); } - | FLOATVAL { $$ = new FloatValue($1); } - | STRINGVAL { $$ = new StringValue($1); } - | ARRAYVAL { $$ = $1; } - | PAREN_OPEN OBJARGS PAREN_CLOSED { $$ = new ObjectValue($2); } - ; - -VARTYPE : TYPE { $$ = new BaseType($1, nullptr); } - | AUTO { $$ = new BaseType($1, nullptr); } - | AUTO ANGLE_OPEN IDENTIFIER ANGLE_CLOSED { $$ = new BaseType($1, $3); } - | FUNC ANGLE_OPEN TYPE_LIST ARROW TYPE_LIST ANGLE_CLOSED { $$ = new FuncType($1, $3, $5); } - | NVAR { $$ = new CustomType($1); } - | VARTYPE CONST { $$ = new ConstType($1); } - | VARTYPE TILDE { $$ = new PointerType($1); } - | VARTYPE SQUARE_OPEN EXPR SQUARE_CLOSED { $$ = new ArrayType($1, $3); } - | VARTYPE SQUARE_OPEN SQUARE_CLOSED { $$ = new ArrayType($1, nullptr); } - ; - -TYPE_LIST : TYPE_LIST COMMA VARTYPE { $$ = $1; $$->push_back($3); } - | VARTYPE { $$ = new std::vector(); $$->push_back($1); } - ; - -NVAR : IDENTIFIER DUBCOLON NVAR { $$ = new Variable($1, $3); } - | IDENTIFIER { $$ = new Variable($1, nullptr); } - ; - -VAR : VAR DOT IDENTIFIER { $$ = new MemberAccess($1, $3); } - | VAR SQUARE_OPEN EXPR SQUARE_CLOSED { $$ = new ArrayAccess($1, $3); } - | VAR PAREN_OPEN ARGS PAREN_CLOSED { $$ = new Call($1, $3); } - | NVAR { $$ = $1; } - ; - -ARRAYVAL : SQUARE_OPEN ARGS SQUARE_CLOSED { $$ = new ArrayValue($2); } - ; - -ARGS : FARGS { $$ = $1; } - | { $$ = new std::vector(); } - ; - -FARGS : FARGS COMMA EXPR { $$ = $1; $$->push_back($3); } - | EXPR { $$ = new std::vector(); $$->push_back($1); } - ; - -OBJARGS : FOBJARGS { $$ = $1; } - | { $$ = new std::vector(); } - ; - -FOBJARGS : FOBJARGS COMMA IDENTIFIER COLON EXPR { $$ = $1; $$->push_back(new VarDec($3, nullptr, $5)); } - | IDENTIFIER COLON EXPR { $$ = new std::vector(); $$->push_back(new VarDec($1, nullptr, $3)); } - ; -%% diff --git a/src/symboltable.cpp b/src/symboltable.cpp deleted file mode 100644 index 9181c1b..0000000 --- a/src/symboltable.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#include "symboltable.hpp" - -std::string ErrorString(ErrorType type) { - switch (type) { - case ErrorType::None: return "None"; - case ErrorType::UhOh: return "Fatal Error!!"; - case ErrorType::Redeclaration: return "Redeclaration"; - case ErrorType::NotFound: return "Not Found"; - case ErrorType::SizeParameterNotNumber: return "Size Parameter Not Number"; - case ErrorType::LhsRhsTypeMismatch: return "Type Mismatch"; - case ErrorType::CastFuncMultipleParams: return "Cast Function Multiple Params"; - case ErrorType::CastFuncMultipleReturns: return "Cast Function Multiple Returns"; - case ErrorType::CastFuncReturnTypeMismatch: return "Cast Function Return Type Mismatch"; - case ErrorType::UnexpectedType: return "Unexpected Type"; - case ErrorType::RuntimeCaseCondition: return "Runtime Determined Case Condition"; - case ErrorType::NoCastExists: return "No Cast Exists"; - case ErrorType::UnknownVariable: return "Unknown Variable"; - case ErrorType::NoMemberVariables: return "No Member Variables"; - case ErrorType::TypeDoesNotHaveMember: return "Type Does Not Have Member"; - case ErrorType::NotIterableType: return "Type Is Not Iterable"; - case ErrorType::DereferenceNonPointer: return "Cannot Dereference A Non-Pointer"; - case ErrorType::OpFuncParameterSizeMismatch: return "Op Function Parameter Size Mismatch"; - default: return "Unknown Error"; - } -} - -bool Symbol::operator==(Symbol other){ - if (type != other.type || - (sub_type != nullptr && other.sub_type != nullptr && *sub_type != *other.sub_type) || - pointer_redirection_level != other.pointer_redirection_level || - custom_type_name != other.custom_type_name || - name != other.name) { - return false; - } else { - if (params == nullptr && other.params == nullptr) return true; - if (params == nullptr || other.params == nullptr) return false; - if (params->size() != other.params->size()) return false; - - for (int i = 0; i < params->size(); i++) { - if (*(*params)[i] != *(*other.params)[i]) { - return false; - } - } - } - return true; -}; - -bool Symbol::operator!=(Symbol other){ - return !(*this == other); -} - -bool Symbol::typeMatch(Symbol* first, Symbol* second) { - if (first == nullptr || second == nullptr) return false; - return (*first == *second) || - (first->isNumber() && second->isNumber()) || - (first->isBoolean() && second->isBoolean()) || - (first->isArray() && second->isArray()); - //TODO add the check for custom types (probably just checking the type entry pointer tbh - // Also need to make sure this works with auto types. I believe this will work for an auto type if it already had it type determined but not in the case of undetermined auto types quite yet -} - -bool Symbol::isNumber() { - return pointer_redirection_level == 0 && - (type == SymType::I16 || type == SymType::I32 || type == SymType::I64 || - type == SymType::S16 || type == SymType::S32 || type == SymType::S64 || - type == SymType::U16 || type == SymType::U32 || type == SymType::U64 || - type == SymType::F32 || type == SymType::F64 || type == SymType::F128 || - type == SymType::Byte || (type != SymType::Array && sub_type && sub_type->isNumber())); //this thing feels weird but it is okay I guess - //This "type != SymType::Array" part is cause we use sub_type to tell what the elements of an array are which resulted in strings being evaluated as numbers since: - // String -> Array(Byte) -> Byte -> Number - //maybe have a "similar_type" instead of "sub_type" or maybe use "element_type" for arrays instead of "sub_type" - -} - -bool Symbol::isBoolean() { - return pointer_redirection_level == 0 && (type == SymType::Boolean || (sub_type && sub_type->isBoolean())); -} - -bool Symbol::isArray() { - return pointer_redirection_level == 0 && (type == SymType::Array || type == SymType::String || (sub_type && sub_type->isArray())); -} - -bool Symbol::isString() { - return pointer_redirection_level == 0 && (type == SymType::String || (type == SymType::Array && sub_type && sub_type->type == SymType::Byte) || (type != SymType::Array && sub_type && sub_type->isString())); -} - -std::string Symbol::toString() { - switch(type) { - case SymType::Error: return "Error"; - case SymType::None: return "None"; - case SymType::Unknown: return "Unknown"; - case SymType::Auto: return "Auto"; - case SymType::Custom: return "Custom"; - case SymType::Variant: return "Variant"; - case SymType::Enum: return "Enum"; - case SymType::Func: return "Func"; - case SymType::Array: return "Array"; - case SymType::String: return "String"; - case SymType::Boolean: return "Boolean"; - case SymType::Byte: return "Byte"; - case SymType::I16: return "I16"; - case SymType::I32: return "I32"; - case SymType::I64: return "I64"; - case SymType::S16: return "S16"; - case SymType::S32: return "S32"; - case SymType::S64: return "S64"; - case SymType::U16: return "U16"; - case SymType::U32: return "U32"; - case SymType::U64: return "U64"; - case SymType::F32: return "F32"; - case SymType::F64: return "F64"; - case SymType::F128: return "F128"; - default: return "HHHHHH"; - } - return ":("; -} - -Symbol* Symbol::copy() { - auto sub_copy = sub_type == nullptr ? nullptr : sub_type->copy(); - auto sym = new Symbol(name, type, sub_copy); - sym->custom_type_name = custom_type_name; - sym->custom_type = custom_type; - - if (params) { - sym->params = new std::vector(); - for (auto p : *params) { - sym->params->push_back(p->copy()); - } - } - if (returns) { - sym->returns = new std::vector(); - for (auto r : *returns) { - sym->returns->push_back(r->copy()); - } - } - - sym->errorType = errorType; - sym->assignable = assignable; - sym->constant = constant; - sym->computed = computed; - sym->pointer_redirection_level = pointer_redirection_level; - - return sym; -} - -Symbol* Symbol::createFunction(std::string name, std::vector* params, std::vector* returns) { - auto symbol = new Symbol(name, SymType::Func, {}); - symbol->params = params; - symbol->returns = returns; - return symbol; -} - -Symbol* Symbol::createArray(std::string name, Symbol* subtype) { - return new Symbol(name, SymType::Array, subtype); -} - -Symbol* Symbol::createError(ErrorType type, std::string name) { - auto symbol = new Symbol(name, SymType::Error, {}); - symbol->errorType = type; - return symbol; -} - -Symbol* Symbol::createNone() { - return new Symbol("", SymType::None, {}); -} - -Symbol* Symbol::createByte() { - return new Symbol("", SymType::Byte, {}); -} - -Symbol* Symbol::createBoolean() { - return new Symbol("", SymType::Boolean, {}); -} - -Symbol* Symbol::createBasic(SymType i) { - return new Symbol("", i, {}); -} - -Symbol* Symbol::createString() { - return new Symbol("", SymType::String, Symbol::createArray("", Symbol::createByte())); -} - -Symbol* Symbol::createHex(int length) { - if (length > 1) { - return Symbol::createArray("", Symbol::createByte()); - } - return Symbol::createByte(); -} - -Symbol* VTable::addDeclaration(std::string name, Symbol* symbol) { - Symbol* result = nullptr; - auto found = declaration_list->find(name); - if (found == declaration_list->end()) { - (*declaration_list)[name] = symbol; - } - return result; -} - -TypeEntry* TypeEntry::createFromTypes(std::string name, std::vector* types) { - auto entry = new TypeEntry(name); - for (auto sym : *types) { - entry->vtable->addDeclaration(sym->name, sym); - } - return entry; -} - -Symbol* TypeEntry::getMember(std::string name) { - if (vtable == nullptr) return nullptr; - auto result = vtable->declaration_list->find(name); - if(result == vtable->declaration_list->end()) return nullptr; - return result->second; -} - - -bool TypeEntry::matchMembers(std::unordered_map* members) { - bool result = true; - for (auto&[name, entry] : *members) { - auto found = vtable->declaration_list->find(name); - if (found == vtable->declaration_list->end() || *entry != *(found->second)) { - result = false; - break; - } - } - return result; -} - -SymbolTable* SymbolTable::createChildScope() { - return createChildScope(""); -} - -SymbolTable* SymbolTable::createChildScope(std::string name) { - auto child = new SymbolTable(this, name); - sub_scopes->push_back(child); - return child; -} - -Symbol* SymbolTable::addSymbol(std::string name, Symbol* type) { - Symbol* result = nullptr; - auto found = current_scope->find(name); - if (found == current_scope->end()) { - //add new symbol - auto group = new std::vector(); - group->push_back(type); - (*current_scope)[name] = group; - } else { - auto group = found->second; - for(auto etype : *group) { - if (*etype == *type) { - result = etype; - break; - } - } - } - return result; -} - -TypeEntry* SymbolTable::addType(std::string name, TypeEntry* type) { - auto found = type_table->find(name); - if (found == type_table->end()) { - (*type_table)[name] = type; - } - return found->second; -} - -Symbol* SymbolTable::getVarSymbol(std::string name) { - Symbol* result = nullptr; - auto found = current_scope->find(name); - if (found != current_scope->end()) { - for (auto sym : *found->second) { - if (sym->type != SymType::Func) { - result = sym; - break; - } - } - } - if (result == nullptr && parent_scope != nullptr) { - //we couldn't find it in this scope so check the next higher one - result = parent_scope->getVarSymbol(name); - } - return result; -} - -Symbol* SymbolTable::getFuncSymbol(std::string name, std::vector* params) { - Symbol* result = nullptr; - auto found = current_scope->find(name); - if (found != current_scope->end()) { - for (auto sym : *found->second) { - if (sym->type != SymType::Func) continue; - if (sym->params->size() == params->size()) { - bool isMatch = true; - for (int i = 0; i < params->size(); i++) { - auto a = (*params)[i]; - auto b = (*sym->params)[i]; - if (a->type != b->type || - *(a->sub_type) != *(b->sub_type) || - a->custom_type_name != b->custom_type_name || - a->pointer_redirection_level != b->pointer_redirection_level) { - isMatch = false; - break; - } - } - if (isMatch) { - result = sym; - break; - } - } - } - } - if (result == nullptr && parent_scope != nullptr) { - result = parent_scope->getVarSymbol(name); - } - return result; -} - -TypeEntry* SymbolTable::getTypeEntry(std::string name) { - TypeEntry* result = nullptr; - auto found = type_table->find(name); - if (found != type_table->end()) { - result = found->second; - } - if (result == nullptr && parent_scope != nullptr) { - //we couldn't find it in this scope so check the next higher one - result = parent_scope->getTypeEntry(name); - } - return result; -} - -TypeEntry* SymbolTable::getTypeEntry(std::unordered_map* members) { - TypeEntry* result = nullptr; - - for(auto&[name, entry] : *type_table) { - if (entry->matchMembers(members)) { - result = entry; - break; - } - } - - if (result == nullptr && parent_scope != nullptr) { - //we couldn't find it in this scope so check the next higher one - result = parent_scope->getTypeEntry(members); - } - return result; -} diff --git a/src/symboltable.hpp b/src/symboltable.hpp deleted file mode 100644 index d9304ee..0000000 --- a/src/symboltable.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once - -#include -#include -#include - -//forward declarations -class AstNode; -class TypeEntry; - -enum class SymType { - Error, None, Unknown, Auto, - Custom, Variant, Enum, - Func, Array, String, - Boolean, Byte, - I16, I32, I64, - S16, S32, S64, - U16, U32, U64, - F32, F64, F128, -}; - -enum class ErrorType { - None, UhOh, Redeclaration, NotFound, SizeParameterNotNumber, - LhsRhsTypeMismatch, CastFuncMultipleParams, CastFuncMultipleReturns, - CastFuncReturnTypeMismatch, UnexpectedType, RuntimeCaseCondition, - NoCastExists, UnknownVariable, NoMemberVariables, TypeDoesNotHaveMember, - NotIterableType, DereferenceNonPointer, OpFuncParameterSizeMismatch -}; - -std::string ErrorString(ErrorType type); - -class Symbol { //these are variables -public: - std::string name = ""; - - SymType type = SymType::Unknown; - Symbol* sub_type = {}; - std::string custom_type_name = ""; - TypeEntry* custom_type = {}; - - std::vector* params = {}; - std::vector* returns = {}; - - ErrorType errorType = ErrorType::None; - AstNode* node = {}; - - bool assignable = false; - bool constant = false; - bool computed = false; - int pointer_redirection_level = 0; //0 is not a pointer, 1 is pointer, 2 is pointer to a pointer, etc etc - - Symbol(std::string n, SymType t, Symbol* st) : name(n), type(t), sub_type(st) {}; - - //exact symbol match - bool operator==(Symbol other); - bool operator!=(Symbol other); - - bool isNumber(); - bool isBoolean(); - bool isArray(); - bool isString(); - - Symbol* copy(); - std::string toString(); - - //only type match / auto type handling - static bool typeMatch(Symbol*, Symbol*); - - static Symbol* createFunction(std::string name, std::vector* params, std::vector* returns); - static Symbol* createArray(std::string name, Symbol* subtype); - static Symbol* createError(ErrorType type, std::string message); - static Symbol* createNone(); - static Symbol* createByte(); - static Symbol* createBoolean(); - static Symbol* createBasic(SymType i); - static Symbol* createString(); - static Symbol* createHex(int length); -}; - -class VTable { -public: - std::unordered_map* declaration_list = {}; - - VTable() { - declaration_list = new std::unordered_map(); - } - - Symbol* addDeclaration(std::string name, Symbol* symbol); -}; - -class TypeEntry { //these are for types -public: - std::string name = ""; - SymType type = SymType::Custom; - Symbol* sub_type = {}; - VTable* vtable = {}; - - TypeEntry(std::string n) : name(n) { - vtable = new VTable(); - }; - - bool matchMembers(std::unordered_map* members); - Symbol* getMember(std::string); - - //useful for creating the custom types we get from multi return functions - static TypeEntry* createFromTypes(std::string name, std::vector* types); -}; - -class SymbolTable { -public: - SymbolTable* parent_scope = {}; - std::vector* sub_scopes = {}; - - std::string namespace_name = ""; - std::unordered_map*>* current_scope = {}; - std::unordered_map* type_table = {}; - - SymbolTable(SymbolTable* pscope, std::string name) : parent_scope(pscope), namespace_name(name) { - sub_scopes = new std::vector(); - current_scope = new std::unordered_map*>(); - type_table = new std::unordered_map(); - } - - //creates a child scope on this scope and sets up the connections properly - SymbolTable* createChildScope(); - SymbolTable* createChildScope(std::string name); - - //add a symbol to the current scope. Return nullptr on success and return the conflicting symbol on redefinition - Symbol* addSymbol(std::string name, Symbol* type); - //add a custom type to the current scope. Return nullptr on success and return the conflicting type on redefinition - TypeEntry* addType(std::string name, TypeEntry* type); - - //a variable and a function can have the same name but a variable cannot share the name as another variable - Symbol* getVarSymbol(std::string name); - //same here but functions can be overloaded so they are matched by their parameters - Symbol* getFuncSymbol(std::string name, std::vector* params); - //there can only be one type per name - TypeEntry* getTypeEntry(std::string name); - //this is useful for searching up a type by the member values so we can get the type of anonymous objects - TypeEntry* getTypeEntry(std::unordered_map* members); -}; diff --git a/src/token.hpp b/src/token.hpp deleted file mode 100644 index 4d189f0..0000000 --- a/src/token.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once - -#include -#include -#include "type_helper.hpp" - -union TokenLexeme -{ - bool bool_lex; - u_64 int_lex; - f_128 float_lex; - char* string_lex; -}; - -enum class TokenType { - //Tokens - Unrecognized, - - Macro, - Newline, - //Keywords - Type, - Auto, - Func, - Op, - Cast, - - Const, - Enum, - Pack, - Variant, - - If, - Else, - For, - In, - By, - While, - Break, - Continue, - Stop, - Switch, - Default, - - //variables and constants - Identifier, - HexCode, - String, - Boolean, - Float, - Integer, - - //operators and symbols - OpAssign, - Shift, - Question, - Range, - Equal, - EqOp, - RelOp, - LogOp, - BitOp, - AddOp, - MultOp, - Apply, - Access, - Not, - - LeftParen, - RightParen, - LeftSquare, - RightSquare, - LeftBrace, - RightBrace, - LeftAngle, - RightAngle, - - Comma, - Colon, - Semicolon, - DubColon, - Carrot, - Tilde, -}; - -class Token -{ -public: - - TokenType type; - TokenLexeme lexeme; - int linenum; - int colnum; - - Token(TokenType t, char* l, int lnum, int cnum) { - type = t; - lexeme.string_lex = l; - linenum = lnum; - colnum = cnum; - }; - - Token(TokenType t, bool l, int lnum, int cnum) { - type = t; - lexeme.bool_lex = l; - linenum = lnum; - colnum = cnum; - }; - - Token(TokenType t, u_64 l, int lnum, int cnum) { - type = t; - lexeme.int_lex = l; - linenum = lnum; - colnum = cnum; - }; - - Token(TokenType t, f_128 l, int lnum, int cnum) { - type = t; - lexeme.float_lex = l; - linenum = lnum; - colnum = cnum; - }; - - std::string toString() { - //std::cout << "in toString()" << std::endl; - std::string s = "{["; - s += std::to_string(linenum) + ":" + std::to_string(colnum) + "]"; - s += "(" + std::to_string((int)type) + ") "; - if(type == TokenType::Integer) - s += std::to_string(lexeme.int_lex); - else if(type == TokenType::Float) - s += std::to_string(lexeme.float_lex); - else if(type == TokenType::Boolean) - s += std::to_string(lexeme.bool_lex); - else - s.append(lexeme.string_lex); - s += "}"; - //std::cout << "done toString()" << std::endl; - return s; - } -}; - diff --git a/src/type_helper.hpp b/src/type_helper.hpp deleted file mode 100644 index b1b09cf..0000000 --- a/src/type_helper.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#define u_16 uint16_t -#define u_32 uint32_t -#define u_64 uint64_t - -#define s_16 uint16_t -#define s_32 uint32_t -#define s_64 uint64_t - -#define f_32 float -#define f_64 double -#define f_128 long double diff --git a/src/typechecker.cpp b/src/typechecker.cpp deleted file mode 100644 index 5fc8c10..0000000 --- a/src/typechecker.cpp +++ /dev/null @@ -1,955 +0,0 @@ -#include "ast.hpp" -#include "helper.hpp" -#include - -SymType getSymTypeFromLexeme(std::string lexeme) { - //This could be better - SymType result = SymType::None; - if(lexeme == "string") result = SymType::String; - if(lexeme == "bool") result = SymType::Boolean; - if(lexeme == "byte") result = SymType::Byte; - if(lexeme == "i16") result = SymType::I16; - if(lexeme == "i32") result = SymType::I32; - if(lexeme == "i64") result = SymType::I64; - if(lexeme == "s16") result = SymType::S16; - if(lexeme == "s32") result = SymType::S32; - if(lexeme == "s64") result = SymType::S64; - if(lexeme == "u16") result = SymType::U16; - if(lexeme == "u32") result = SymType::U32; - if(lexeme == "u64") result = SymType::U64; - if(lexeme == "f32") result = SymType::F32; - if(lexeme == "f64") result = SymType::F64; - if(lexeme == "f128") result = SymType::F128; - return result; -} - -void VariantDec::buildVTable(VTable* vtable, SymbolTable* table) { - -} - -void PackDec::buildVTable(VTable* vtable, SymbolTable* table) { - -} - -void EnumDec::buildVTable(VTable* vtable, SymbolTable* table) { - -} - -void OpFuncDec::buildVTable(VTable* vtable, SymbolTable* table) { - //this should also just add the operator function to the table and not the vtable -} - -void CastFuncDec::buildVTable(VTable* vtable, SymbolTable* table) { - //this should actually just add the cast function to the table and not the vtable -} - -void FuncDec::buildVTable(VTable* vtable, SymbolTable* table) { - -} - -void VarDec::buildVTable(VTable* vtable, SymbolTable* table) { - -} - -Symbol* BaseType::buildSymbolTable(SymbolTable* table) { - SymType mainType = (_type->type == TokenType::Auto) ? SymType::Auto : getSymTypeFromLexeme(_type->lexeme.string_lex); - - symbol = new Symbol("", mainType, {}); - - if (_type->type == TokenType::Auto && _auto_name != nullptr) { - TypeEntry* autoType = new TypeEntry(_auto_name->lexeme.string_lex); - autoType->type = SymType::Unknown; - auto t_result = table->addType(_auto_name->lexeme.string_lex, autoType); - if (t_result != nullptr) { - auto temp = symbol; - symbol = Symbol::createError(ErrorType::Redeclaration, "This auto type name is already another type or another anonymous type in this scope."); - symbol->node = this; - symbol->sub_type = temp; - return symbol; - } - - symbol->custom_type = autoType; - symbol->custom_type_name = _auto_name->lexeme.string_lex; - } - symbol->node = this; - return symbol; -} - -Symbol* CustomType::buildSymbolTable(SymbolTable* table) { - symbol = new Symbol("", SymType::Custom, {}); - //TODO add namespacing here. maybe even allow you to pass a "Variable" type in here and do the namespacing in the symbol table functions - auto found = table->getTypeEntry(_type->_name->lexeme.string_lex); - if (found == nullptr) { - auto temp = Symbol::createError(ErrorType::NotFound, "Type not found"); - temp->node = this; - symbol = temp; - return symbol; - } - symbol->type = found->type; - symbol->sub_type = found->sub_type; - symbol->custom_type = found; - symbol->custom_type_name = found->name; - symbol->node = this; - return symbol; -} - -Symbol* FuncType::buildSymbolTable(SymbolTable* table) { - auto params = new std::vector(); - for (auto par : *_param_types) { - par->buildSymbolTable(table); - params->push_back(par->symbol); - } - - auto returns = new std::vector(); - for (auto ret : *_return_types) { - ret->buildSymbolTable(table); - returns->push_back(ret->symbol); - } - - //TODO what if one of the returns or one of the params has an error in it's type? - symbol = Symbol::createFunction("", params, returns); - symbol->node = this; - return symbol; -} - -Symbol* ConstType::buildSymbolTable(SymbolTable* table) { - _type->buildSymbolTable(table); - if (_type->symbol->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There is an error further down the tree."); - symbol->node = this; - return symbol; - } - - symbol = _type->symbol; - symbol->constant = true; - symbol->node = this; - return symbol; -} - -Symbol* PointerType::buildSymbolTable(SymbolTable* table) { - _type->buildSymbolTable(table); - if (_type->symbol->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There is an error further down the tree."); - symbol->node = this; - return symbol; - } - - symbol = _type->symbol; - symbol->pointer_redirection_level += 1; - symbol->node = this; - return symbol; -} - -Symbol* ArrayType::buildSymbolTable(SymbolTable* table) { - _type->buildSymbolTable(table); - if (_type->symbol->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There is an error further down the tree."); - symbol->node = this; - return symbol; - } - - if (_array_length) _array_length->buildSymbolTable(table); - if (_array_length && !_array_length->symbol->isNumber()) { - symbol = Symbol::createError(ErrorType::SizeParameterNotNumber, "The size parameter of this array type is not an number."); - symbol->sub_type = Symbol::createArray("", _type->symbol); - } else { - symbol = Symbol::createArray("", _type->symbol); - } - symbol->node = this; - return symbol; -} - -Symbol* Parameter::buildSymbolTable(SymbolTable* table) { - _type->buildSymbolTable(table); - if (_type->symbol->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There is an error further down the tree."); - symbol->node = this; - return symbol; - } - symbol = _type->symbol; - symbol->name = _id->lexeme.string_lex; - symbol->node = this; - return symbol; -} - -Symbol* Program::buildSymbolTable(SymbolTable* table) { - Symbol* result = nullptr; - for (auto stmt : *_stmts) { - auto s_result = stmt->buildSymbolTable(table); - if (s_result->type == SymType::Error && result == nullptr) { - result = Symbol::createError(ErrorType::None, "There is an error further down the tree"); - } - } - if (result == nullptr) { - symbol = Symbol::createNone(); - symbol->node = this; - } else { - symbol = result; - symbol->node = this; - } - return symbol; -} - -Symbol* Macro::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createNone(); - symbol->node = this; - return symbol; -} - -Symbol* CompoundStmt::buildSymbolTable(SymbolTable* table) { - Symbol* result = nullptr; - for (auto stmt : *_stmts) { - auto s_result = stmt->buildSymbolTable(table); - if (s_result->type == SymType::Error && result == nullptr) { - result = Symbol::createError(ErrorType::None, "There is an error further down the tree"); - } - } - if (result == nullptr) { - symbol = Symbol::createNone(); - } else { - symbol = result; - } - symbol->node = this; - return symbol; -} - -Symbol* VarDec::buildSymbolTable(SymbolTable* table) { - auto t_result = _type->buildSymbolTable(table); - if (t_result->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There is an error further down in the tree."); - symbol->node = this; - std::cout << "Type error >:(" << std::endl; - if (_expr) _expr->symbol = Symbol::createNone(); - return symbol; - } - - symbol = _type->symbol; - symbol->assignable = true; - symbol->name = _id->lexeme.string_lex; - auto result = table->addSymbol(_id->lexeme.string_lex, symbol); - if (_expr) { - auto e_result = _expr->buildSymbolTable(table); - if (e_result->type == SymType::Error) { - auto temp = Symbol::createError(ErrorType::None, "diublaiusdbf"); - temp->sub_type = symbol; - temp->node = this; - symbol = temp; - return symbol; - } - - if (!Symbol::typeMatch(symbol, _expr->symbol)) { - Symbol* orig = symbol; - symbol = Symbol::createError(ErrorType::LhsRhsTypeMismatch, "The right hand side of the assignement does not have the same type as the left hand side"); - symbol->sub_type = orig; - } - } - if (result != nullptr) { - symbol = Symbol::createError(ErrorType::Redeclaration, "This variable has already been declared"); - symbol->sub_type = result; - } - symbol->node = this; - return symbol; -} - -Symbol* FuncDec::buildSymbolTable(SymbolTable* table) { - auto child = table->createChildScope(); - auto params = new std::vector(); - for (auto par : *_params) { - par->buildSymbolTable(table); - params->push_back(par->symbol); - if(par->symbol->type != SymType::Error) - child->addSymbol(par->symbol->name, par->symbol); - } - - auto returns = new std::vector(); - for (auto ret : *_returns) { - ret->buildSymbolTable(table); - returns->push_back(ret->symbol); - if(ret->symbol->type != SymType::Error) - child->addSymbol(ret->symbol->name, ret->symbol); - } - - symbol = Symbol::createFunction(_id->lexeme.string_lex, params, returns); - symbol->node = this; - - auto func_sym = table->addSymbol(_id->lexeme.string_lex, symbol); - if (func_sym != nullptr) { - symbol = Symbol::createError(ErrorType::Redeclaration, "An operator function alrady exists for this operator and parameter types."); - symbol->node = this; - return symbol; - } - - auto result = _body->buildSymbolTable(child); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "There was an error in the body of this function."); - newError->sub_type = symbol; - symbol = newError; - symbol->node = this; - } - - return symbol; -} - -Symbol* OpFuncDec::buildSymbolTable(SymbolTable* table) { - auto child = table->createChildScope(); - auto params = new std::vector(); - for (auto par : *_params) { - par->buildSymbolTable(table); - params->push_back(par->symbol); - if(par->symbol->type != SymType::Error) - child->addSymbol(par->symbol->name, par->symbol); - } - - auto returns = new std::vector(); - for (auto ret : *_returns) { - ret->buildSymbolTable(table); - returns->push_back(ret->symbol); - if(ret->symbol->type != SymType::Error) - child->addSymbol(ret->symbol->name, ret->symbol); - } - - switch(_op->type) { - //one or two params - case TokenType::AddOp: - if (_params->size() < 1 || _params->size() > 2) { - symbol = Symbol::createError(ErrorType::OpFuncParameterSizeMismatch, "This operator function can only have one or two parameters."); - } - break; - //exactly one param - case TokenType::Not: - case TokenType::Question: - case TokenType::Tilde: - if (_params->size() != 1) { - symbol = Symbol::createError(ErrorType::OpFuncParameterSizeMismatch, "This operator function can only have one parameter."); - } - break; - //exactly two params - case TokenType::LogOp: - case TokenType::BitOp: - case TokenType::EqOp: - case TokenType::RelOp: - case TokenType::LeftAngle: - case TokenType::RightAngle: - case TokenType::Shift: - case TokenType::MultOp: - case TokenType::Range: - if (_params->size() != 2) { - symbol = Symbol::createError(ErrorType::OpFuncParameterSizeMismatch, "This operator function can only have two parameters."); - } - break; - default: - break; - } - if (symbol != nullptr) { - symbol->node = this; - return symbol; - } - - symbol = Symbol::createFunction(_op->lexeme.string_lex, params, returns); - symbol->node = this; - - auto func_sym = table->addSymbol(_op->lexeme.string_lex, symbol); - if (func_sym != nullptr) { - symbol = Symbol::createError(ErrorType::Redeclaration, "An operator function alrady exists for this operator and parameter types."); - symbol->node = this; - return symbol; - } - - auto result = _body->buildSymbolTable(child); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "There was an error in the body of this function."); - newError->sub_type = symbol; - symbol = newError; - symbol->node = this; - } - return symbol; -} - -Symbol* CastFuncDec::buildSymbolTable(SymbolTable* table) { - auto child = table->createChildScope(); - auto params = new std::vector(); - for (auto par : *_params) { - par->buildSymbolTable(table); - params->push_back(par->symbol); - if(par->symbol->type != SymType::Error) - child->addSymbol(par->symbol->name, par->symbol); - } - - auto returns = new std::vector(); - for (auto ret : *_returns) { - ret->buildSymbolTable(table); - returns->push_back(ret->symbol); - if(ret->symbol->type != SymType::Error) - child->addSymbol(ret->symbol->name, ret->symbol); - } - - if (_params->size() != 1) { - symbol = Symbol::createError(ErrorType::CastFuncMultipleParams, "A cast function can only have a single parameter."); - symbol->node = this; - return symbol; - } - - if (_returns->size() != 1) { - symbol = Symbol::createError(ErrorType::CastFuncMultipleReturns, "A cast function can only have a single return."); - symbol->node = this; - return symbol; - } - - _casting_type->buildSymbolTable(table); - auto a = _casting_type->symbol; - auto b = (*returns)[0]; - if (!Symbol::typeMatch(a, b)) { - symbol = Symbol::createError(ErrorType::CastFuncReturnTypeMismatch, "The casting type must match the return type of a cast function."); - symbol->node = this; - return symbol; //maybe don't return here - } - - std::string castName = "cast-" + _casting_type->toCastString(); - - symbol = Symbol::createFunction(castName, params, returns); - symbol->node = this; - - auto func_sym = table->addSymbol(castName, symbol); - if (func_sym != nullptr) { - symbol = Symbol::createError(ErrorType::Redeclaration, "A casting function already exists for this set of types in this order."); - symbol->node = this; - return symbol; - } - - auto result = _body->buildSymbolTable(child); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "There was an error in the body of this function."); - newError->sub_type = symbol; - symbol = newError; - symbol->node = this; - } - return symbol; -} - -Symbol* EnumDec::buildSymbolTable(SymbolTable* table) { - auto result = new TypeEntry(_id->lexeme.string_lex); - _base_type->buildSymbolTable(table); - result->sub_type = _base_type->symbol; - auto vtable = new VTable(); - for(auto dec : *_declist) { - dec->buildVTable(vtable, table); - } - result->vtable = vtable; - table->addType(result->name, result); - - symbol = new Symbol(result->name, SymType::Enum, _base_type->symbol); - symbol->node = this; - symbol->custom_type = result; - symbol->custom_type_name = result->name; - return symbol; -} - -Symbol* PackDec::buildSymbolTable(SymbolTable* table) { - auto result = new TypeEntry(_id->lexeme.string_lex); - auto vtable = new VTable(); - for(auto dec : *_declist) { - dec->buildVTable(vtable, table); - } - result->vtable = vtable; - table->addType(result->name, result); - - symbol = new Symbol(result->name, SymType::Custom, {}); - symbol->node = this; - symbol->custom_type = result; - symbol->custom_type_name = result->name; - return symbol; -} - -Symbol* VariantDec::buildSymbolTable(SymbolTable* table) { - auto result = new TypeEntry(_id->lexeme.string_lex); - auto vtable = new VTable(); - for(auto dec : *_declist) { - dec->buildVTable(vtable, table); - } - result->vtable = vtable; - table->addType(result->name, result); - - symbol = new Symbol(result->name, SymType::Variant, {}); - symbol->node = this; - symbol->custom_type = result; - symbol->custom_type_name = result->name; - return symbol; -} - -Symbol* IfStmt::buildSymbolTable(SymbolTable* table) { - _cond->buildSymbolTable(table); - if (_cond->symbol->type != SymType::Boolean) { - symbol = Symbol::createError(ErrorType::UnexpectedType, "The condition for if statements must evaluate to a boolean."); - } - - auto result = _body->buildSymbolTable(table); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "There was an error in the true branch of this if block."); - newError->sub_type = symbol; - symbol = newError; - } - - if (_elseBody) { - auto e_result = _elseBody->buildSymbolTable(table); - if (e_result->type == SymType::Error) { - if (symbol->errorType == ErrorType::None) { - symbol->name = "There was an error in both the if and the else branches"; - } else { - auto newError = Symbol::createError(ErrorType::None, "There was an error in the false branch of this if block."); - newError->sub_type = symbol; - symbol = newError; - } - } - } - - if (symbol == nullptr) { - symbol = Symbol::createNone(); - } - - symbol->node = this; - return symbol; -} - -Symbol* SwitchCase::buildSymbolTable(SymbolTable* table) { - if (_case) { - auto result = _case->buildSymbolTable(table); - if (result->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There was an error in the condition of this switch case"); - symbol->node = this; - _body->symbol = Symbol::createNone(); - return symbol; - } - } - - if (_case && !_case->symbol->computed) { - symbol = Symbol::createError(ErrorType::RuntimeCaseCondition, "The case condition must be able to be evaluated at compile time. If you are doing calculations in the case condition make sure any variables are determined at compile-time."); - symbol->node = this; - return symbol; - } - - auto switchcase = table->createChildScope(""); - auto result = _body->buildSymbolTable(switchcase); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "There was an error in the body of this case."); - newError->sub_type = symbol; - symbol = newError; - } - - if (symbol == nullptr) { - symbol = Symbol::createNone(); - } - - symbol->node = this; - return symbol; -} - -Symbol* SwitchStmt::buildSymbolTable(SymbolTable* table) { - _cond->buildSymbolTable(table); - - Symbol* result = nullptr; - for (auto scase : *_cases) { - auto c_result = scase->buildSymbolTable(table); - if (c_result->type != SymType::Error && !Symbol::typeMatch(scase->symbol, _cond->symbol)) { - auto orig = scase->symbol; - scase->symbol = Symbol::createError(ErrorType::UnexpectedType, "The case condition doesn't match the switch condition."); - scase->symbol->sub_type = orig; - scase->symbol->node = scase; - } - if (c_result->type == SymType::Error && result == nullptr) { - auto result = Symbol::createError(ErrorType::None, "There was an error in one of the case statements"); - symbol = result; - } - } - - if (symbol == nullptr) { - symbol = Symbol::createNone(); - } - - symbol->node = this; - return symbol; -} - -Symbol* WhileStmt::buildSymbolTable(SymbolTable* table) { - _cond->buildSymbolTable(table); - //check for is boolean - if (!_cond->symbol->isBoolean()) { - symbol = Symbol::createError(ErrorType::UnexpectedType, "The while condition must evaluate to a boolean."); - symbol->node = this; - return symbol; - } - - auto whilechild = table->createChildScope(""); - auto result = _body->buildSymbolTable(whilechild); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "The body of this while loop has an error in it."); - newError->sub_type = symbol; - symbol = newError; - } - - if (symbol == nullptr) { - symbol = Symbol::createNone(); - } - - symbol->node = this; - return symbol; -} - -Symbol* ForStmt::buildSymbolTable(SymbolTable* table) { - auto i_result = _iter->buildSymbolTable(table); - auto b_result = _by ? _by->buildSymbolTable(table) : nullptr; - - if (i_result->type == SymType::Error || (b_result != nullptr && b_result->type == SymType::Error)) { - symbol = Symbol::createError(ErrorType::None, "There was an error in the iterator or the by number"); - symbol->node = this; - _body->symbol = Symbol::createNone(); - return symbol; - } - - if (!_iter->symbol->isArray()) { - symbol = Symbol::createError(ErrorType::UnexpectedType, "Iterator must be evaluate to an array type."); - symbol->node = this; - _body->symbol = Symbol::createNone(); - return symbol; - } - - if (_by != nullptr && !_by->symbol->isNumber()) { - symbol = Symbol::createError(ErrorType::UnexpectedType, "By must evaluate to a number."); - symbol->node = this; - _body->symbol = Symbol::createNone(); - return symbol; - } - - auto forscope = table->createChildScope(""); - auto itersym = _iter->symbol->copy(); - itersym->name = _id->lexeme.string_lex; - forscope->addSymbol(_id->lexeme.string_lex, itersym); - - auto result = _body->buildSymbolTable(forscope); - if (result->type == SymType::Error) { - auto newError = Symbol::createError(ErrorType::None, "The body of this for loop has an error in it."); - newError->sub_type = symbol; - symbol = newError; - } - - if (symbol == nullptr) { - symbol = Symbol::createNone(); - } - - symbol->node = this; - return symbol; -} - -Symbol* ExprStmt::buildSymbolTable(SymbolTable* table) { - _expr->buildSymbolTable(table); - if (_expr->symbol->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There is an error further down the tree"); - } else { - symbol = Symbol::createNone(); - } - symbol->node = this; - return symbol; -} - -Symbol* StopStmt::buildSymbolTable(SymbolTable* table) { symbol = Symbol::createNone(); symbol->node = this; return symbol; } - -Symbol* BreakStmt::buildSymbolTable(SymbolTable* table) { symbol = Symbol::createNone(); symbol->node = this; return symbol; } - -Symbol* ContinueStmt::buildSymbolTable(SymbolTable* table) { symbol = Symbol::createNone(); symbol->node = this; return symbol; } - -Symbol* Variable::buildSymbolTable(SymbolTable* table) { - std::string varname = _name->lexeme.string_lex; - auto var = table->getVarSymbol(varname); - if (var == nullptr) { - symbol = Symbol::createError(ErrorType::UnknownVariable, "This variable could not be found from the current scope."); - } else { - symbol = var->copy(); - } - symbol->node = this; - return symbol; -} - -Symbol* MemberAccess::buildSymbolTable(SymbolTable* table) { - auto result = _parent->buildSymbolTable(table); - if (result->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There was an error in the parent of this member access"); - symbol->node = this; - return symbol; - } - - if (result->custom_type == nullptr) { - symbol = Symbol::createError(ErrorType::NoMemberVariables, "This variable has no member variables."); - } else { - auto member = _parent->symbol->custom_type->getMember(_id->lexeme.string_lex); - if (member == nullptr) { - symbol = Symbol::createError(ErrorType::TypeDoesNotHaveMember, "This type does not have a member variable with that name."); - } else { - symbol = member->copy(); - } - } - - symbol->node = this; - return symbol; -} - -Symbol* ArrayAccess::buildSymbolTable(SymbolTable* table) { - auto p_result = _parent->buildSymbolTable(table); - auto e_result = _expr->buildSymbolTable(table); - - if (p_result->type == SymType::Error || e_result->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "klasjdfhalskdj"); - symbol->node = this; - return symbol; - } - - if(p_result->type == SymType::Array) { - if (e_result->isNumber()) { - symbol = p_result->sub_type->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "Indexes for an iterable type must be a number."); - } - } else { - symbol = Symbol::createError(ErrorType::NotIterableType, "This type is not iterable so it cannot be accessed through array access."); - } - - symbol->node = this; - return symbol; -} - -Symbol* Call::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createError(ErrorType::UhOh, "Call typecheck not implemented"); - symbol->node = this; - return symbol; -} - -Symbol* Assignment::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createError(ErrorType::UhOh, "Assignment typecheck not implemented"); - symbol->node = this; - return symbol; -} - -Symbol* BinaryExpr::buildSymbolTable(SymbolTable* table) { - auto left = _left->buildSymbolTable(table); - auto right = _right->buildSymbolTable(table); - if (left->type == SymType::Error || right->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There was an error furter down the tree."); - symbol->node = this; - return symbol; - } - - switch(_op->type) { - case TokenType::EqOp: - if (Symbol::typeMatch(left, right)) { - symbol = Symbol::createBoolean(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::RelOp: - case TokenType::LeftAngle: - case TokenType::RightAngle: - if (left->isNumber() && right->isNumber()) { - symbol = Symbol::createBoolean(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::Shift: - if ((left->isNumber() || - (left->isArray() && left->sub_type->isNumber()) || - (left->isArray() && left->sub_type->isBoolean())) && - right->isNumber()) { - symbol = left->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::LogOp: - if (left->isBoolean() && right->isBoolean()) { - symbol = Symbol::createBoolean(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::BitOp: - if (Symbol::typeMatch(left, right) && - (left->isNumber() || left->isBoolean() || - (left->isArray() && left->sub_type->isNumber()) || - (left->isArray() && left->sub_type->isBoolean()))) { - symbol = left->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::AddOp: - if ((left->isNumber() && right->isNumber()) || - (left->isString() && right->isString())) { - symbol = left->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::MultOp: - if (left->isNumber() && right->isNumber()) { - symbol = left->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - case TokenType::Range: - if (left->isNumber() && right->isNumber()) { - symbol = Symbol::createArray("", left->copy()); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied types."); - } - break; - default: - symbol = Symbol::createError(ErrorType::UhOh, "We should not have gotten this error. Unknown binary expression operator!!!!"); - break; - } - - symbol->node = this; - return symbol; -} - -Symbol* UnaryExpr::buildSymbolTable(SymbolTable* table) { - auto result = _expr->buildSymbolTable(table); - if (result->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "There was an error further down the tree."); - symbol->node = this; - return symbol; - } - - //TODO make this look up any operator overloaded functions - switch (_op->type) { - case TokenType::Not: - if (result->isBoolean()) { - symbol = result->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied type."); - } - break; - case TokenType::AddOp: - if (result->isNumber()) { - //TODO make this change unsigned numbers to signed numbers (but not backwards) - symbol = result->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied type."); - } - break; - case TokenType::Tilde: //binary not - if (result->isNumber() || result->isBoolean() || - (result->isArray() && result->sub_type->isNumber()) || - (result->isArray() && result->sub_type->isBoolean())) { - symbol = result->copy(); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "This operator does not have an implicit or explicit definition for the supplied type."); - } - break; - case TokenType::Question: - symbol = result->copy(); - if (symbol->pointer_redirection_level < 1) { - symbol = Symbol::createError(ErrorType::DereferenceNonPointer, "Cannot dereference a non-pointer."); - } else { - symbol->pointer_redirection_level -= 1; - } - break; - default: - symbol = Symbol::createError(ErrorType::UhOh, "We should not have gotten this error. Unknown unary expression operator!!!!"); - break; - } - - symbol->node = this; - return symbol; -} - -Symbol* Cast::buildSymbolTable(SymbolTable* table) { - auto t_result = _type->buildSymbolTable(table); - auto e_result = _expr->buildSymbolTable(table); - if (t_result->type == SymType::Error || e_result->type == SymType::Error) { - symbol = Symbol::createError(ErrorType::None, "akshdfl"); - symbol->node = this; - return symbol; - } - - if (!Symbol::typeMatch(_type->symbol, _expr->symbol)) { - std::string castFunc = "cast-" + _type->toCastString(); - auto castSym = table->getFuncSymbol(castFunc, new std::vector { _expr->symbol }); - if (castSym != nullptr) { - symbol = _type->symbol->copy(); - } else { - symbol = Symbol::createError(ErrorType::NoCastExists, "No cast exists to the supplied type. Define your own cast function or cast to a different type."); - } - } - else - { - symbol = _type->symbol->copy(); - } - - symbol->node = this; - return symbol; -} - -Symbol* IntValue::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createBasic(SymType::U64); - symbol->node = this; - return symbol; -} - -Symbol* HexValue::buildSymbolTable(SymbolTable* table) { - std::string value = _value->lexeme.string_lex; - int byte_length = value.length() % 2 == 0 ? value.length() / 2 : (value.length() + 1) / 2; - symbol = Symbol::createHex(byte_length); - symbol->node = this; - return symbol; -} - -Symbol* BoolValue::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createBoolean(); - symbol->node = this; - return symbol; -} - -Symbol* FloatValue::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createBasic(SymType::F128); - symbol->node = this; - return symbol; -} - -Symbol* StringValue::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createString(); - symbol->node = this; - return symbol; -} - -Symbol* ArrayValue::buildSymbolTable(SymbolTable* table) { - Symbol* type = nullptr; - bool valid = true; - bool error = false; - for (auto elem : *_elements) { - auto etype = elem->buildSymbolTable(table); - if (type == nullptr && etype->type != SymType::Error) { - type = etype->copy(); - } else if (etype->type == SymType::Error) { - error = true; - } else if (!Symbol::typeMatch(etype, type)){ - valid = false; - } - } - - if (valid && !error) { - symbol = Symbol::createArray("", type); - } else if (error) { - symbol = Symbol::createError(ErrorType::None, "asldkjfas"); - } else { - symbol = Symbol::createError(ErrorType::UnexpectedType, "Each element of the array must evaluate to the same type."); - } - - symbol->node = this; - return symbol; -} - -Symbol* ObjectValue::buildSymbolTable(SymbolTable* table) { - symbol = Symbol::createNone(); - symbol->node = this; - return symbol; -} diff --git a/tests/hello_world.rs b/tests/hello_world.rs new file mode 100644 index 0000000..7ba5205 --- /dev/null +++ b/tests/hello_world.rs @@ -0,0 +1,6 @@ +pub use ocean::compiler::{compile}; + +#[test] +pub fn hello_world_test() { + assert_eq!("hello", "world"); +} \ No newline at end of file diff --git a/tests/test.sea b/tests/test.sea deleted file mode 100644 index e6b5b8d..0000000 --- a/tests/test.sea +++ /dev/null @@ -1,49 +0,0 @@ -pack myPack { - a: f32 - b: f32 - packFunc: () -> (sum: f32, diff: f32, prod: f32, quot: f32) { - sum = a + b - diff = a - b - prod = a * b - quot = a / b - } -} - -enum Types { - a: 0; - b #= 1 - c #= 2 - d: 10; -} - -func: (yeah: auto, oh: T) -> (a: i32, b: i32) { - switch yeah { - Types::a -> { - a = 5 - b = 7 + 13 - continue # this falls through into the b case - } - Types::b -> { - a = b - } - Types::c || Types::d -> { - q = asdff - } - default -> { - what = 5 + 6 * 2 - } - } -} - -main: () -> (ret: i32) { - if 4 { - yeah = baby - } else { - baby = yeah - } - - ooo: myPack = (a: 12, b: 32) - ooo.packFunc() - - why: auto = func(54 * 43, 65 << 23) -} \ No newline at end of file diff --git a/tests/test2.sea b/tests/test2.sea deleted file mode 100644 index ec9e3c1..0000000 --- a/tests/test2.sea +++ /dev/null @@ -1,8 +0,0 @@ -a: i32 = 1234 * 5 -b: string = "q" + "q" -c: i32 = 16 >> 5 - -#I don't know if I like this syntax for arrays :/ -d: i32[] = 1...5 -e: u64[5] = 1...5 -#f: i32 = 1...5 \ No newline at end of file