diff --git a/.gitignore b/.gitignore index 567609b..438c44a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build/ +.cache +generated/ diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index b24aab9..f79d0b2 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -1,18 +1,29 @@ -cmake_minimum_required(VERSION 3.25) +cmake_minimum_required(VERSION 3.22.1) project(plasmatum) set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) -set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD 20) set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) set(INC_DIR ${CMAKE_SOURCE_DIR}/include) set(GEN_DIR ${CMAKE_SOURCE_DIR}/generated) +file(GLOB_RECURSE sources ${SRC_DIR}/*.cpp ${SRC_DIR}/**/*.cpp) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) +include(ExternalAntlr4Cpp) + +find_package( + Boost 1.84 REQUIRED + COMPONENTS json +) + +# Generate ANTLR4 Files set(ANTLR_INC ${INC_DIR}/plsmLexer.h ${INC_DIR}/plsmParser.h ${INC_DIR}/plsmVisitor.h ${INC_DIR}/plsmBaseVisitor.h) set(ANTLR_SRC ${SRC_DIR}/plsmLexer.cpp ${SRC_DIR}/plsmParser.cpp ${SRC_DIR}/plsmVisitor.cpp ${SRC_DIR}/plsmBaseVisitor.cpp) - add_custom_command(PRE_BUILD DEPENDS ${CMAKE_SOURCE_DIR}/plsm.g4 OUTPUT ${ANTLR_SRC} @@ -25,14 +36,15 @@ add_custom_command(PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${GEN_DIR}/*.h ${INC_DIR} COMMAND ${CMAKE_COMMAND} -E copy ${GEN_DIR}/*.cpp ${SRC_DIR}) -file(GLOB_RECURSE sources ${SRC_DIR}/*.cpp) set(sources ${sources} ${ANTLR_SRC}) add_executable(plsm ${sources}) +add_dependencies(plsm antlr4_static) target_include_directories(plsm PRIVATE ${CMAKE_SOURCE_DIR}/include) -target_include_directories(plsm PRIVATE /usr/include/antlr4-runtime) -target_link_libraries(plsm antlr4-runtime) +target_include_directories(plsm PRIVATE ${ANTLR4_INCLUDE_DIRS}) +target_link_directories(plsm PRIVATE ${ANTLR4_OUTPUT_DIR}) +target_link_libraries(plsm PRIVATE antlr4-runtime Boost::json) add_custom_target(clean-all COMMAND ${CMAKE_COMMAND} -E rm -rf diff --git a/compiler/adscript.g4 b/compiler/adscript.g4 deleted file mode 100644 index 5869127..0000000 --- a/compiler/adscript.g4 +++ /dev/null @@ -1,8 +0,0 @@ -grammar adscript; - -module:; - -// TODO ;) - -FN: 'fn'; -TYPE: 'type'; diff --git a/compiler/cmake/ExternalAntlr4Cpp.cmake b/compiler/cmake/ExternalAntlr4Cpp.cmake new file mode 100644 index 0000000..4da7fbc --- /dev/null +++ b/compiler/cmake/ExternalAntlr4Cpp.cmake @@ -0,0 +1,178 @@ +cmake_minimum_required(VERSION 3.7) + +if(POLICY CMP0114) + cmake_policy(SET CMP0114 NEW) +endif() + +include(ExternalProject) + +set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime) +set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src) +# set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git) +set(ANTLR4_ZIP_REPOSITORY ${PROJECT_SOURCE_DIR}/thirdparty/antlr-4.13.1.zip) +if(NOT DEFINED ANTLR4_TAG) + # Set to branch name to keep library updated at the cost of needing to rebuild after 'clean' + # Set to commit hash to keep the build stable and does not need to rebuild after 'clean' + set(ANTLR4_TAG master) +endif() + +# Ensure that the include dir already exists at configure time (to avoid cmake erroring +# on non-existent include dirs) +file(MAKE_DIRECTORY "${ANTLR4_INCLUDE_DIRS}") + +if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") + set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/runtime/$(Configuration)) +elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*") + set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/runtime/$(CONFIGURATION)) +else() + set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/runtime) +endif() + +if(MSVC) + set(ANTLR4_STATIC_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/antlr4-runtime-static.lib) + set(ANTLR4_SHARED_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/antlr4-runtime.lib) + set(ANTLR4_RUNTIME_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/antlr4-runtime.dll) +else() + set(ANTLR4_STATIC_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.a) + if(MINGW) + set(ANTLR4_SHARED_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a) + set(ANTLR4_RUNTIME_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll) + elseif(CYGWIN) + set(ANTLR4_SHARED_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a) + set(ANTLR4_RUNTIME_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.13.1.dll) + elseif(APPLE) + set(ANTLR4_RUNTIME_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib) + else() + set(ANTLR4_RUNTIME_LIBRARIES + ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.so) + endif() +endif() + +if(${CMAKE_GENERATOR} MATCHES ".* Makefiles") + # This avoids + # 'warning: jobserver unavailable: using -j1. Add '+' to parent make rule.' + set(ANTLR4_BUILD_COMMAND $(MAKE)) +elseif(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") + set(ANTLR4_BUILD_COMMAND + ${CMAKE_COMMAND} + --build . + --config $(Configuration) + --target) +elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*") + set(ANTLR4_BUILD_COMMAND + ${CMAKE_COMMAND} + --build . + --config $(CONFIGURATION) + --target) +else() + set(ANTLR4_BUILD_COMMAND + ${CMAKE_COMMAND} + --build . + --target) +endif() + +if(NOT DEFINED ANTLR4_WITH_STATIC_CRT) + set(ANTLR4_WITH_STATIC_CRT ON) +endif() + +if(ANTLR4_ZIP_REPOSITORY) + ExternalProject_Add( + antlr4_runtime + PREFIX antlr4_runtime + URL ${ANTLR4_ZIP_REPOSITORY} + DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR} + BUILD_COMMAND "" + BUILD_IN_SOURCE 1 + SOURCE_DIR ${ANTLR4_ROOT} + SOURCE_SUBDIR runtime/Cpp + CMAKE_CACHE_ARGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DWITH_STATIC_CRT:BOOL=${ANTLR4_WITH_STATIC_CRT} + -DDISABLE_WARNINGS:BOOL=ON + # -DCMAKE_CXX_STANDARD:STRING=17 # if desired, compile the runtime with a different C++ standard + # -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} # alternatively, compile the runtime with the same C++ standard as the outer project + INSTALL_COMMAND "" + EXCLUDE_FROM_ALL 1) +else() + ExternalProject_Add( + antlr4_runtime + PREFIX antlr4_runtime + GIT_REPOSITORY ${ANTLR4_GIT_REPOSITORY} + GIT_TAG ${ANTLR4_TAG} + DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR} + BUILD_COMMAND "" + BUILD_IN_SOURCE 1 + SOURCE_DIR ${ANTLR4_ROOT} + SOURCE_SUBDIR runtime/Cpp + CMAKE_CACHE_ARGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DWITH_STATIC_CRT:BOOL=${ANTLR4_WITH_STATIC_CRT} + -DDISABLE_WARNINGS:BOOL=ON + # -DCMAKE_CXX_STANDARD:STRING=17 # if desired, compile the runtime with a different C++ standard + # -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} # alternatively, compile the runtime with the same C++ standard as the outer project + INSTALL_COMMAND "" + EXCLUDE_FROM_ALL 1) +endif() + +# Separate build step as rarely people want both +set(ANTLR4_BUILD_DIR ${ANTLR4_ROOT}) +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0") + # CMake 3.14 builds in above's SOURCE_SUBDIR when BUILD_IN_SOURCE is true + set(ANTLR4_BUILD_DIR ${ANTLR4_ROOT}/runtime/Cpp) +endif() + +ExternalProject_Add_Step( + antlr4_runtime + build_static + COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_static + # Depend on target instead of step (a custom command) + # to avoid running dependent steps concurrently + DEPENDS antlr4_runtime + BYPRODUCTS ${ANTLR4_STATIC_LIBRARIES} + EXCLUDE_FROM_MAIN 1 + WORKING_DIRECTORY ${ANTLR4_BUILD_DIR}) +ExternalProject_Add_StepTargets(antlr4_runtime build_static) + +add_library(antlr4_static STATIC IMPORTED) +add_dependencies(antlr4_static antlr4_runtime-build_static) +set_target_properties(antlr4_static PROPERTIES + IMPORTED_LOCATION ${ANTLR4_STATIC_LIBRARIES}) +target_include_directories(antlr4_static + INTERFACE + ${ANTLR4_INCLUDE_DIRS} +) + +ExternalProject_Add_Step( + antlr4_runtime + build_shared + COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_shared + # Depend on target instead of step (a custom command) + # to avoid running dependent steps concurrently + DEPENDS antlr4_runtime + BYPRODUCTS ${ANTLR4_SHARED_LIBRARIES} ${ANTLR4_RUNTIME_LIBRARIES} + EXCLUDE_FROM_MAIN 1 + WORKING_DIRECTORY ${ANTLR4_BUILD_DIR}) +ExternalProject_Add_StepTargets(antlr4_runtime build_shared) + +add_library(antlr4_shared SHARED IMPORTED) +add_dependencies(antlr4_shared antlr4_runtime-build_shared) +set_target_properties(antlr4_shared PROPERTIES + IMPORTED_LOCATION ${ANTLR4_RUNTIME_LIBRARIES}) +target_include_directories(antlr4_shared + INTERFACE + ${ANTLR4_INCLUDE_DIRS} +) + +if(ANTLR4_SHARED_LIBRARIES) + set_target_properties(antlr4_shared PROPERTIES + IMPORTED_IMPLIB ${ANTLR4_SHARED_LIBRARIES}) +endif() diff --git a/compiler/dev.Dockerfile b/compiler/dev.Dockerfile deleted file mode 100644 index b1d22a9..0000000 --- a/compiler/dev.Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM ubuntu:latest - -RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends \ - cmake clang \ - llvm-15 llvm-15-dev llvm-15-doc llvm-15-tools \ - mlir-15-tools libmlir-15 libmlir-15-dev \ - libboost-dev libboost-doc - - diff --git a/compiler/include/AST/Base.h b/compiler/include/AST/Base.h index d2027ab..5943484 100644 --- a/compiler/include/AST/Base.h +++ b/compiler/include/AST/Base.h @@ -1,56 +1,128 @@ #pragma once -#include -#include +#include +#include #include +#include +#include +#include +#include +#include + +#include #define LOC_ARG const Location &location -namespace ast -{ - class Location - { - public: - Location(const std::string &file, std::pair start, std::pair end) - : file(file), start(start), end(end) {} +namespace plsm { +namespace ast { - const std::string file; - const std::pair start, end; - }; +class Location { +public: + Location(const std::string &file, std::pair start, + std::pair end) + : file(file), start(start), end(end) {} - class ASTNode - { - public: - ASTNode(LOC_ARG) : location(location) {} - virtual ~ASTNode() = default; + const std::string file; + const std::pair start, end; - const Location location; + static Location json() { return Location("", {-1, -1}, {-1, -1}); }; +}; - virtual std::string str() = 0; +class ASTNode { +public: + ASTNode(LOC_ARG) : location(location) {} + virtual ~ASTNode() = default; - virtual bool isExpr() { return false; } - virtual bool isStmt() { return false; } - virtual bool isType() { return false; } - }; + const Location location; - class Expr : public ASTNode - { - public: - Expr(LOC_ARG) : ASTNode(location) {} - virtual bool isExpr() override { return true; } - }; + virtual boost::json::value toJson() = 0; - class Stmt : public ASTNode - { - public: - Stmt(LOC_ARG) : ASTNode(location) {} - virtual bool isStmt() override { return true; } - }; + virtual std::string toJsonString() { + return boost::json::serialize(toJson()); + } - class Type : public ASTNode - { - public: - Type(LOC_ARG) : ASTNode(location) {} - virtual bool isType() override { return true; } - }; -} \ No newline at end of file + static std::unique_ptr fromJson(boost::json::value json); + + virtual bool isExpr() { return false; } + virtual bool isStmt() { return false; } + virtual bool isType() { return false; } + +protected: + template + static inline boost::json::value getJsonProperty(boost::json::value json, + std::string property) { + boost::json::value prop; + try { + if (!json.as_object().contains(property)) + throw std::exception(); + prop = json.as_object().at(property); + } catch (...) { + std::cout << boost::json::serialize(json) << std::endl; + throw std::runtime_error("missing property '" + property + "' in " + + typeid(CurrNode).name() + "::fromJson"); + } + + return prop; + } + + template + static inline T getJsonValue(boost::json::value json, std::string property) { + auto prop = getJsonProperty(json, property); + try { + return boost::json::value_to(prop); + } catch (...) { + throw std::runtime_error("invalid value for property '" + property + + "' in " + typeid(CurrNode).name() + + "::fromJson"); + } + } + + template + static inline auto fromJsonProperty(boost::json::value json, + std::string property) { + return SubNode::fromJson(getJsonProperty(json, property)); + } + + template + static inline auto fromJsonVector(boost::json::value json, + std::string property) { + auto arr = getJsonProperty(json, property).as_array(); + + std::vector> result; + for (auto &el : arr) { + result.push_back(SubNode::fromJson(el)); + } + + return result; + } +}; + +class Expr : public ASTNode { +public: + Expr(LOC_ARG) : ASTNode(location) {} + + static std::unique_ptr fromJson(boost::json::value json); + + virtual bool isExpr() override { return true; } +}; + +class Stmt : public ASTNode { +public: + Stmt(LOC_ARG) : ASTNode(location) {} + + static std::unique_ptr fromJson(boost::json::value json); + + virtual bool isStmt() override { return true; } +}; + +class Type : public ASTNode { +public: + Type(LOC_ARG) : ASTNode(location) {} + + static std::unique_ptr fromJson(boost::json::value json); + + virtual bool isType() override { return true; } +}; + +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/BinExpr.h b/compiler/include/AST/Expr/BinExpr.h index 0a298d7..bb5fb93 100644 --- a/compiler/include/AST/Expr/BinExpr.h +++ b/compiler/include/AST/Expr/BinExpr.h @@ -1,45 +1,38 @@ #pragma once #include "AST/Base.h" -#include +#include #include +#include +#include -namespace ast -{ - class BinExpr : public Expr - { - const std::string op; - const std::unique_ptr left, right; +namespace plsm { +namespace ast { - public: - BinExpr(LOC_ARG, std::unique_ptr &left, const std::string &op, std::unique_ptr &right) - : Expr(location), left(std::move(left)), op(op), right(std::move(right)) {} +class BinExpr : public Expr { + const std::string op; + const std::unique_ptr left, right; - virtual std::string str(size_t indent, size_t tabstop) - { - return (std::stringstream() << "BinExpr(" - << "op=\"" << op << "\", " - << "left=" << left->str() << ", " - << "right=" << right->str() - << ")") - .str(); - } - }; +public: + BinExpr(LOC_ARG, std::unique_ptr &left, const std::string &op, + std::unique_ptr &right) + : Expr(location), left(std::move(left)), op(op), right(std::move(right)) { + } - class PrefExpr : public Expr - { - const std::unique_ptr expr; + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; - public: - PrefExpr(LOC_ARG, std::unique_ptr &expr) - : Expr(location), expr(std::move(expr)) {} +class PrefExpr : public Expr { + const std::unique_ptr expr; - virtual std::string str() - { - return (std::stringstream() << "PrefExpr(" - << "expr=" << expr->str() - << ")") - .str(); - } - }; -} \ No newline at end of file +public: + PrefExpr(LOC_ARG, std::unique_ptr &expr) + : Expr(location), expr(std::move(expr)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; + +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/Block.h b/compiler/include/AST/Expr/Block.h index 7f230ad..7b7843c 100644 --- a/compiler/include/AST/Expr/Block.h +++ b/compiler/include/AST/Expr/Block.h @@ -1,38 +1,25 @@ #pragma once #include "AST/Base.h" -#include #include +#include +#include -namespace ast -{ - class BlockExpr : public Expr - { - const std::vector> stmts; - const std::unique_ptr result; +namespace plsm { +namespace ast { - public: - BlockExpr(LOC_ARG, std::vector> &stmts, std::unique_ptr &result) - : Expr(location), stmts(std::move(stmts)), result(std::move(result)) {} +class BlockExpr : public Expr { + const std::vector> stmts; + const std::unique_ptr result; - virtual std::string str() - { - std::stringstream ss; - ss << "BlockExpr("; +public: + BlockExpr(LOC_ARG, std::vector> &stmts, + std::unique_ptr &result) + : Expr(location), stmts(std::move(stmts)), result(std::move(result)) {} - ss << "stmts=["; - for (size_t i = 0; i < stmts.size(); i++) - { - ss << stmts[i]->str(); - if (i != stmts.size() - 1) - ss << ", "; - } - ss << "], "; + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; - ss << "result=" << result->str(); - ss << ")"; - - return ss.str(); - } - }; -} \ No newline at end of file +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/Call.h b/compiler/include/AST/Expr/Call.h index dbdad9a..e7d8dbe 100644 --- a/compiler/include/AST/Expr/Call.h +++ b/compiler/include/AST/Expr/Call.h @@ -1,39 +1,25 @@ #pragma once #include "AST/Base.h" -#include #include +#include +#include -namespace ast -{ - class CallExpr : public Expr - { - const std::unique_ptr callee; - const std::vector> args; +namespace plsm { +namespace ast { - public: - CallExpr(LOC_ARG, std::unique_ptr &callee, std::vector> &args) - : Expr(location), callee(std::move(callee)), args(std::move(args)) {} +class CallExpr : public Expr { + const std::unique_ptr callee; + const std::vector> args; - virtual std::string str() - { - std::stringstream ss; +public: + CallExpr(LOC_ARG, std::unique_ptr &callee, + std::vector> &args) + : Expr(location), callee(std::move(callee)), args(std::move(args)) {} - ss << "CallExpr("; - ss << "callee=" << callee->str(); + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; - ss << "args=["; - for (size_t i = 0; i < args.size(); i++) - { - ss << args[i]->str(); - if (i != args.size() - 1) - ss << ", "; - } - ss << "]"; - - ss << ")"; - - return ss.str(); - } - }; -} \ No newline at end of file +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/Closure.h b/compiler/include/AST/Expr/Closure.h index 84b0af1..a04e720 100644 --- a/compiler/include/AST/Expr/Closure.h +++ b/compiler/include/AST/Expr/Closure.h @@ -1,38 +1,25 @@ #pragma once #include "AST/Base.h" +#include +#include #include #include -#include -namespace ast -{ - class Closure : public Expr - { - const std::vector args; - const std::unique_ptr body; +namespace plsm { +namespace ast { +class FnArg; - public: - Closure(LOC_ARG, std::vector &args, std::unique_ptr &body) - : Expr(location), args(std::move(args)), body(std::move(body)) {} +class Closure : public Expr { + const std::vector> args; + const std::unique_ptr body; - virtual std::string str() - { - std::stringstream ss; +public: + Closure(LOC_ARG, std::vector> &args, std::unique_ptr &body) + : Expr(location), args(std::move(args)), body(std::move(body)) {} - ss << "CallExpr("; - ss << "args=["; - for (size_t i = 0; i < args.size(); i++) - { - ss << args[i]; - if (i != args.size() - 1) - ss << ", "; - } - ss << "], "; - ss << "body=" << body->str(); - ss << ")"; - - return ss.str(); - } - }; -} \ No newline at end of file + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/Identifier.h b/compiler/include/AST/Expr/Identifier.h index a9d5236..384b32e 100644 --- a/compiler/include/AST/Expr/Identifier.h +++ b/compiler/include/AST/Expr/Identifier.h @@ -3,19 +3,17 @@ #include "AST/Base.h" #include -namespace ast -{ - class Identifier : public Expr - { - const std::string name; +namespace plsm { +namespace ast { +class Identifier : public Expr { + const std::string name; - public: - Identifier(LOC_ARG, const std::string &name) - : Expr(location), name(name) {} +public: + Identifier(LOC_ARG, const std::string &name) : Expr(location), name(name) {} - virtual std::string str() - { - return "Identifier(" + name + ")"; - } - }; -} \ No newline at end of file + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; + +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/PropExpr.h b/compiler/include/AST/Expr/PropExpr.h index ad837ab..564c826 100644 --- a/compiler/include/AST/Expr/PropExpr.h +++ b/compiler/include/AST/Expr/PropExpr.h @@ -2,26 +2,21 @@ #include "AST/Base.h" #include +#include #include -namespace ast -{ - class PropExpr : public Expr - { - const std::unique_ptr expr; - const std::string property; +namespace plsm { +namespace ast { +class PropExpr : public Expr { + const std::unique_ptr expr; + const std::string property; - public: - PropExpr(LOC_ARG, std::unique_ptr &expr, const std::string &property) - : Expr(location), expr(std::move(expr)), property(property) {} +public: + PropExpr(LOC_ARG, std::unique_ptr &expr, const std::string &property) + : Expr(location), expr(std::move(expr)), property(property) {} - virtual std::string str() - { - return (std::stringstream() << "PropExpr(" - << "expr=" << expr->str() << ", " - << "property=" << property - << ")") - .str(); - } - }; -} \ No newline at end of file + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/Tuple.h b/compiler/include/AST/Expr/Tuple.h index 9857937..db45bf2 100644 --- a/compiler/include/AST/Expr/Tuple.h +++ b/compiler/include/AST/Expr/Tuple.h @@ -1,17 +1,23 @@ #pragma once #include "AST/Base.h" -#include #include +#include +#include -namespace ast -{ - class Tuple : public Expr - { - const std::vector> values; +namespace plsm { +namespace ast { - public: - Tuple(LOC_ARG, std::vector> &values) - : Expr(location), values(std::move(values)) {} - }; -} \ No newline at end of file +class Tuple : public Expr { + const std::vector> values; + +public: + Tuple(LOC_ARG, std::vector> &values) + : Expr(location), values(std::move(values)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; + +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/UnaryExpr.h b/compiler/include/AST/Expr/UnaryExpr.h index 5d67466..1809242 100644 --- a/compiler/include/AST/Expr/UnaryExpr.h +++ b/compiler/include/AST/Expr/UnaryExpr.h @@ -1,18 +1,23 @@ #pragma once #include "AST/Base.h" -#include +#include #include +#include +#include -namespace ast -{ - class UnaryExpr : public Expr - { - const std::string op; - const std::unique_ptr expr; +namespace plsm { +namespace ast { +class UnaryExpr : public Expr { + const std::string op; + const std::unique_ptr expr; - public: - UnaryExpr(LOC_ARG, const std::string &op, std::unique_ptr &expr) - : Expr(location), op(op), expr(std::move(expr)) {} - }; -} \ No newline at end of file +public: + UnaryExpr(LOC_ARG, const std::string &op, std::unique_ptr &expr) + : Expr(location), op(op), expr(std::move(expr)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Expr/Value.h b/compiler/include/AST/Expr/Value.h index 44acb0f..32c730c 100644 --- a/compiler/include/AST/Expr/Value.h +++ b/compiler/include/AST/Expr/Value.h @@ -1,31 +1,38 @@ #pragma once #include "AST/Base.h" +#include #include +#include -namespace ast -{ - class NullValue : public Expr - { - public: - NullValue(LOC_ARG) : Expr(location) {} - }; +namespace plsm { +namespace ast { +class NullValue : public Expr { +public: + NullValue(LOC_ARG) : Expr(location) {} - class IntValue : public Expr - { - const int64_t value; + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; - public: - IntValue(LOC_ARG, int64_t value) - : Expr(location), value(value) {} - }; +class IntValue : public Expr { + const std::int64_t value; - class FloatValue : public Expr - { - const double value; +public: + IntValue(LOC_ARG, int64_t value) : Expr(location), value(value) {} - public: - FloatValue(LOC_ARG, double value) - : Expr(location), value(value) {} - }; -} + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; + +class FloatValue : public Expr { + const std::double_t value; + +public: + FloatValue(LOC_ARG, double value) : Expr(location), value(value) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Module/Import.h b/compiler/include/AST/Module/Import.h index fc974a2..c0b8038 100644 --- a/compiler/include/AST/Module/Import.h +++ b/compiler/include/AST/Module/Import.h @@ -1,16 +1,21 @@ #pragma once #include "AST/Base.h" +#include +#include #include -namespace ast -{ - class Import : public ASTNode - { - const std::string moduleName; +namespace plsm { +namespace ast { +class Import : public ASTNode { + const std::string moduleName; - public: - Import(LOC_ARG, const std::string &moduleName) - : ASTNode(location), moduleName(moduleName) {} - }; -} \ No newline at end of file +public: + Import(LOC_ARG, const std::string &moduleName) + : ASTNode(location), moduleName(moduleName) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Module/Module.h b/compiler/include/AST/Module/Module.h index 51bbe67..84140c2 100644 --- a/compiler/include/AST/Module/Module.h +++ b/compiler/include/AST/Module/Module.h @@ -1,21 +1,30 @@ #pragma once #include "AST/Base.h" -#include +#include +#include #include +#include +#include -namespace ast -{ - class Import; +namespace plsm { +namespace ast { +class Import; - class Module : public ASTNode - { - const std::string name; - const std::vector> imports; - const std::vector> stmts; +class Module : public ASTNode { + const std::string name; + const std::vector> imports; + const std::vector> stmts; - public: - Module(LOC_ARG, const std::string &name, std::vector> &imports, std::vector> &stmts) - : ASTNode(location), name(name), imports(std::move(imports)), stmts(std::move(stmts)) {} - }; -} \ No newline at end of file +public: + Module(LOC_ARG, const std::string &name, + std::vector> &imports, + std::vector> &stmts) + : ASTNode(location), name(name), imports(std::move(imports)), + stmts(std::move(stmts)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/ExprStmt.h b/compiler/include/AST/Stmt/ExprStmt.h index df31979..9ec58d8 100644 --- a/compiler/include/AST/Stmt/ExprStmt.h +++ b/compiler/include/AST/Stmt/ExprStmt.h @@ -3,14 +3,17 @@ #include "AST/Base.h" #include -namespace ast -{ - class ExprStmt : public Stmt - { - const std::unique_ptr expr; +namespace plsm { +namespace ast { +class ExprStmt : public Stmt { + const std::unique_ptr expr; - public: - ExprStmt(LOC_ARG, std::unique_ptr &expr) - : Stmt(location), expr(std::move(expr)) {} - }; -} \ No newline at end of file +public: + ExprStmt(LOC_ARG, std::unique_ptr &expr) + : Stmt(location), expr(std::move(expr)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/FnDef.h b/compiler/include/AST/Stmt/FnDef.h index f2d241f..7d57ece 100644 --- a/compiler/include/AST/Stmt/FnDef.h +++ b/compiler/include/AST/Stmt/FnDef.h @@ -1,31 +1,41 @@ #pragma once #include "AST/Base.h" -#include -#include +#include #include +#include +#include +#include -namespace ast -{ - class FnArg : public ASTNode - { - const std::string name; - const std::unique_ptr type; +namespace plsm { +namespace ast { +class FnArg : public ASTNode { + const std::string name; + const std::unique_ptr type; - public: - FnArg(LOC_ARG, const std::string &name, std::unique_ptr &type) - : ASTNode(location), name(name), type(std::move(type)) {} - }; +public: + FnArg(LOC_ARG, const std::string &name, std::unique_ptr &type) + : ASTNode(location), name(name), type(std::move(type)) {} - class FnDef : public Stmt - { - const std::string name; - const std::vector> args; - const std::unique_ptr returnType; - const std::unique_ptr body; + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; - public: - FnDef(LOC_ARG, const std::string &name, std::vector> &args, std::unique_ptr &returnType, std::unique_ptr &body) - : Stmt(location), name(name), args(std::move(args)), returnType(std::move(returnType)), body(std::move(body)) {} - }; -} \ No newline at end of file +class FnDef : public Stmt { + const std::string name; + const std::vector> args; + const std::unique_ptr returnType; + const std::unique_ptr body; + +public: + FnDef(LOC_ARG, const std::string &name, + std::vector> &args, + std::unique_ptr &returnType, std::unique_ptr &body) + : Stmt(location), name(name), args(std::move(args)), + returnType(std::move(returnType)), body(std::move(body)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/TraitAlias.h b/compiler/include/AST/Stmt/TraitAlias.h index 3185f7c..9ad1723 100644 --- a/compiler/include/AST/Stmt/TraitAlias.h +++ b/compiler/include/AST/Stmt/TraitAlias.h @@ -1,19 +1,24 @@ #pragma once #include "AST/Base.h" -#include -#include +#include #include +#include +#include +#include -namespace ast -{ - class TraitAlias : public Stmt - { - const std::string alias; - const std::string aliased; +namespace plsm { +namespace ast { +class TraitAlias : public Stmt { + const std::string alias; + const std::string aliased; - public: - TraitAlias(LOC_ARG, const std::string &alias, const std::string &aliased) - : Stmt(location), alias(alias), aliased(aliased) {} - }; -} \ No newline at end of file +public: + TraitAlias(LOC_ARG, const std::string &alias, const std::string &aliased) + : Stmt(location), alias(alias), aliased(aliased) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/TraitDef.h b/compiler/include/AST/Stmt/TraitDef.h index bab027a..946a055 100644 --- a/compiler/include/AST/Stmt/TraitDef.h +++ b/compiler/include/AST/Stmt/TraitDef.h @@ -1,21 +1,26 @@ #pragma once #include "AST/Base.h" -#include -#include +#include #include +#include +#include +#include -namespace ast -{ - class FnDef; +namespace plsm { +namespace ast { +class FnDef; +class TraitDef : public Stmt { + const std::string name; + const std::vector> traits; - class TraitDef : public Stmt - { - const std::string name; - const std::vector> traits; +public: + TraitDef(LOC_ARG, const std::string &name, + std::vector> &traits) + : Stmt(location), name(name), traits(std::move(traits)) {} - public: - TraitDef(LOC_ARG, const std::string &name, std::vector> &traits) - : Stmt(location), name(name), traits(std::move(traits)) {} - }; -} \ No newline at end of file + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/TypeAlias.h b/compiler/include/AST/Stmt/TypeAlias.h index b7b9c96..97a3060 100644 --- a/compiler/include/AST/Stmt/TypeAlias.h +++ b/compiler/include/AST/Stmt/TypeAlias.h @@ -1,19 +1,24 @@ #pragma once #include "AST/Base.h" -#include -#include +#include #include +#include +#include +#include -namespace ast -{ - class TypeAlias : public Stmt - { - const std::string alias; - const std::unique_ptr type; +namespace plsm { +namespace ast { +class TypeAlias : public Stmt { + const std::string alias; + const std::unique_ptr type; - public: - TypeAlias(LOC_ARG, const std::string &alias, std::unique_ptr &type) - : Stmt(location), alias(alias), type(std::move(type)) {} - }; -} \ No newline at end of file +public: + TypeAlias(LOC_ARG, const std::string &alias, std::unique_ptr &type) + : Stmt(location), alias(alias), type(std::move(type)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/TypeDef.h b/compiler/include/AST/Stmt/TypeDef.h index b008b56..883bd1c 100644 --- a/compiler/include/AST/Stmt/TypeDef.h +++ b/compiler/include/AST/Stmt/TypeDef.h @@ -1,23 +1,29 @@ #pragma once #include "AST/Base.h" -#include -#include #include +#include +#include -namespace ast -{ - class FnDef; - class FnArg; +namespace plsm { +namespace ast { +class FnDef; +class FnArg; - class TypeDef : public Stmt - { - const std::string name; - const std::vector> attrs; - const std::vector> members; +class TypeDef : public Stmt { + const std::string name; + const std::vector> attrs; + const std::vector> members; - public: - TypeDef(LOC_ARG, const std::string &name, std::vector> &attrs, std::vector> &members) - : Stmt(location), name(name), attrs(std::move(attrs)), members(std::move(members)) {} - }; -} \ No newline at end of file +public: + TypeDef(LOC_ARG, const std::string &name, + std::vector> &attrs, + std::vector> &members) + : Stmt(location), name(name), attrs(std::move(attrs)), + members(std::move(members)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Stmt/ValDecl.h b/compiler/include/AST/Stmt/ValDecl.h index 9f3dc20..3f65947 100644 --- a/compiler/include/AST/Stmt/ValDecl.h +++ b/compiler/include/AST/Stmt/ValDecl.h @@ -1,19 +1,24 @@ #pragma once #include "AST/Base.h" -#include #include +#include -namespace ast -{ - class ValDecl : public Stmt - { - const std::string name; - const std::unique_ptr type; - const std::unique_ptr value; +namespace plsm { +namespace ast { +class ValDecl : public Stmt { + const std::string name; + const std::unique_ptr type; + const std::unique_ptr value; - public: - ValDecl(LOC_ARG, const std::string &name, std::unique_ptr &type, std::unique_ptr &value) - : Stmt(location), name(name), type(std::move(type)), value(std::move(value)) {} - }; -} \ No newline at end of file +public: + ValDecl(LOC_ARG, const std::string &name, std::unique_ptr &type, + std::unique_ptr &value) + : Stmt(location), name(name), type(std::move(type)), + value(std::move(value)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Type/Closure.h b/compiler/include/AST/Type/Closure.h index db15d1e..06a432f 100644 --- a/compiler/include/AST/Type/Closure.h +++ b/compiler/include/AST/Type/Closure.h @@ -1,18 +1,23 @@ #pragma once #include "AST/Base.h" -#include #include +#include -namespace ast -{ - class ClosureType : public Type - { - const std::vector> from; - const std::unique_ptr to; +namespace plsm { +namespace ast { +class ClosureType : public Type { + const std::vector> from; + const std::unique_ptr to; - public: - ClosureType(LOC_ARG, std::vector> &from, std::unique_ptr &to) - : Type(location), from(std::move(from)), to(std::move(to)) {} - }; -} \ No newline at end of file +public: + ClosureType(LOC_ARG, std::vector> &from, + std::unique_ptr &to) + : Type(location), from(std::move(from)), to(std::move(to)) {} + + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Type/Generic.h b/compiler/include/AST/Type/Generic.h index bb47146..33443d0 100644 --- a/compiler/include/AST/Type/Generic.h +++ b/compiler/include/AST/Type/Generic.h @@ -1,19 +1,23 @@ #pragma once #include "AST/Base.h" +#include #include #include -#include -namespace ast -{ - class GenericType : public Type - { - const std::string name; - const std::vector> types; +namespace plsm { +namespace ast { +class GenericType : public Type { + const std::string name; + const std::vector> types; - public: - GenericType(LOC_ARG, const std::string &name, std::vector> &types) - : Type(location), name(name), types(std::move(types)) {} - }; -} +public: + GenericType(LOC_ARG, const std::string &name, + std::vector> &types) + : Type(location), name(name), types(std::move(types)) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Type/Named.h b/compiler/include/AST/Type/Named.h index de3c73d..bb51a49 100644 --- a/compiler/include/AST/Type/Named.h +++ b/compiler/include/AST/Type/Named.h @@ -3,14 +3,18 @@ #include "AST/Base.h" #include -namespace ast -{ - class NamedType : public Type - { - const std::string name; +namespace plsm { +namespace ast { - public: - NamedType(LOC_ARG, const std::string &name) - : Type(location), name(name) {} - }; -} \ No newline at end of file +class NamedType : public Type { + const std::string name; + +public: + NamedType(LOC_ARG, const std::string &name) : Type(location), name(name) {} + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; + +} // namespace ast +} // namespace plsm diff --git a/compiler/include/AST/Type/Tuple.h b/compiler/include/AST/Type/Tuple.h index 68accfc..b80f4ec 100644 --- a/compiler/include/AST/Type/Tuple.h +++ b/compiler/include/AST/Type/Tuple.h @@ -1,17 +1,21 @@ #pragma once #include "AST/Def.h" -#include #include +#include -namespace ast -{ - class TupleType : public Type - { - const std::vector> types; +namespace plsm { +namespace ast { +class TupleType : public Type { + const std::vector> types; - public: - TupleType(LOC_ARG, std::vector> &types) - : Type(location), types(std::move(types)) {} - }; -} \ No newline at end of file +public: + TupleType(LOC_ARG, std::vector> &types) + : Type(location), types(std::move(types)) {} + + + virtual boost::json::value toJson() override; + static std::unique_ptr fromJson(boost::json::value json); +}; +} // namespace ast +} // namespace plsm diff --git a/compiler/include/Parser.h b/compiler/include/Parser.h index 833a659..2904152 100644 --- a/compiler/include/Parser.h +++ b/compiler/include/Parser.h @@ -4,15 +4,9 @@ #include #include "AST/Def.h" -#include "plsmLexer.h" -#include "plsmParser.h" namespace plsm { std::unique_ptr parse(const std::string &file, const std::string &input); } -namespace adscript -{ - std::unique_ptr parse(const std::string &file, const std::string &input); -} diff --git a/compiler/include/Utils.h b/compiler/include/Utils.h new file mode 100644 index 0000000..79bc489 --- /dev/null +++ b/compiler/include/Utils.h @@ -0,0 +1,24 @@ +#include +#include +#include + +namespace plsm { +namespace utils { + +template auto mapToJson(const std::vector &vector) { + boost::json::array result(vector.size()); + for (size_t i = 0; i < vector.size(); i++) + result[i] = vector[i]->toJson(); + return result; +} + +template +auto mapToJson(const std::vector &vector, const Mapper &mapper) { + boost::json::array result(vector.size()); + for (size_t i = 0; i < vector.size(); i++) + result[i] = mapper(vector[i]); + return result; +} + +} // namespace utils +} // namespace plsm diff --git a/compiler/plsm.g4 b/compiler/plsm.g4 index a999b73..56493b4 100644 --- a/compiler/plsm.g4 +++ b/compiler/plsm.g4 @@ -36,7 +36,7 @@ typeList: type (',' type)*; expr: expr3; // novisit expr3: expr2 - | '[' identifierList? ']' '->' expr // closure + | '[' fnDefArgs? ']' '->' expr // closure | '{' blockStmt* (expr ';') '}'; expr2: expr1 | expr2 operator expr1; // binary expr diff --git a/compiler/setup/llvm b/compiler/setup/llvm deleted file mode 100755 index a4f2b10..0000000 --- a/compiler/setup/llvm +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/bash - -BASEDIR=$(dirname $(realpath "$0")) - -cd "$BASEDIR/../compiler/thirdparty/llvm-project" - -mkdir -p build -cd build - -cmake -G Ninja ../llvm \ - -DLLVM_ENABLE_PROJECTS="mlir;llvm;lld" \ - -DLLVM_BUILD_EXAMPLES=ON \ - -DLLVM_TARGETS_TO_BUILD="Native;NVPTX;AMDGPU" \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_ENABLE_ASSERTIONS=ON - -cmake --build . diff --git a/compiler/src/AST/Base.cpp b/compiler/src/AST/Base.cpp new file mode 100644 index 0000000..2ac86ff --- /dev/null +++ b/compiler/src/AST/Base.cpp @@ -0,0 +1,113 @@ +#include "AST/Def.h" +#include "AST/Expr/BinExpr.h" +#include "AST/Expr/Value.h" + +#include +#include +#include + +namespace plsm { + +std::unique_ptr ast::ASTNode::fromJson(boost::json::value json) { + if (json.is_null()) + return std::make_unique(ast::Location::json()); + + if (json.is_int64()) + return std::make_unique(ast::Location::json(), json.as_int64()); + + if (json.is_double()) + return std::make_unique(ast::Location::json(), + json.as_double()); + + std::string type; + try { + type = json.as_object().at("@type").as_string().c_str(); + } catch (...) { + throw std::runtime_error( + "called ASTNode::fromJson without @type constraint"); + } + + if (type == "BinExpr") + return ast::BinExpr::fromJson(json); + if (type == "BlockExpr") + return ast::BlockExpr::fromJson(json); + if (type == "CallExpr") + return ast::CallExpr::fromJson(json); + if (type == "Closure") + return ast::Closure::fromJson(json); + if (type == "Identifier") + return ast::Identifier::fromJson(json); + if (type == "PropExpr") + return ast::PropExpr::fromJson(json); + if (type == "Tuple") + return ast::Tuple::fromJson(json); + if (type == "UnaryExpr") + return ast::UnaryExpr::fromJson(json); + + if (type == "Import") + return ast::Import::fromJson(json); + if (type == "Module") + return ast::Module::fromJson(json); + + if (type == "ExprStmt") + return ast::ExprStmt::fromJson(json); + if (type == "FnDef") + return ast::FnDef::fromJson(json); + if (type == "TraitAlias") + return ast::TraitAlias::fromJson(json); + if (type == "TraitDef") + return ast::TraitDef::fromJson(json); + if (type == "TypeAlias") + return ast::TypeAlias::fromJson(json); + if (type == "TypeDef") + return ast::TypeDef::fromJson(json); + if (type == "ValDecl") + return ast::ValDecl::fromJson(json); + + if (type == "ClosureType") + return ast::ClosureType::fromJson(json); + if (type == "GenericType") + return ast::GenericType::fromJson(json); + if (type == "NamedType") + return ast::NamedType::fromJson(json); + if (type == "TupleType") + return ast::TupleType::fromJson(json); + + throw std::runtime_error("json conversion for '" + type + + "' not implemented"); +} + +std::unique_ptr ast::Expr::fromJson(boost::json::value json) { + auto node = ast::ASTNode::fromJson(json); + + if (dynamic_cast(node.get())) { + return std::unique_ptr((ast::Expr *)node.release()); + } + + throw std::runtime_error(json.as_object().at("@type").as_string().c_str() + + std::string(" is not of type 'Expr'")); +} + +std::unique_ptr ast::Type::fromJson(boost::json::value json) { + auto node = ast::ASTNode::fromJson(json); + + if (dynamic_cast(node.get())) { + return std::unique_ptr((ast::Type *)node.release()); + } + + throw std::runtime_error(json.as_object().at("@type").as_string().c_str() + + std::string(" is not of type 'Type'")); +} + +std::unique_ptr ast::Stmt::fromJson(boost::json::value json) { + auto node = ast::ASTNode::fromJson(json); + + if (dynamic_cast(node.get())) { + return std::unique_ptr((ast::Stmt *)node.release()); + } + + throw std::runtime_error(json.as_object().at("@type").as_string().c_str() + + std::string(" is not of type 'Stmt'")); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/BinExpr.cpp b/compiler/src/AST/Expr/BinExpr.cpp new file mode 100644 index 0000000..4a76f25 --- /dev/null +++ b/compiler/src/AST/Expr/BinExpr.cpp @@ -0,0 +1,37 @@ +#include "AST/Expr/BinExpr.h" +#include "AST/Base.h" +#include "AST/Def.h" +#include + +namespace plsm { + +boost::json::value ast::BinExpr::toJson() { + return { + {"@type", "BinExpr"}, + {"op", op}, + {"left", left->toJson()}, + {"right", right->toJson()}, + }; +} + +std::unique_ptr ast::BinExpr::fromJson(boost::json::value json) { + auto op = getJsonValue(json, "op"); + auto left = fromJsonProperty(json, "left"); + auto right = fromJsonProperty(json, "right"); + return std::make_unique(ast::Location::json(), left, op, right); +} + +boost::json::value ast::PrefExpr::toJson() { + return { + {"@type", "PrefExpr"}, + {"expr", expr->toJson()}, + }; +} + +std::unique_ptr +ast::PrefExpr::fromJson(boost::json::value json) { + auto expr = fromJsonProperty(json, "expr"); + return std::make_unique(ast::Location::json(), expr); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/Block.cpp b/compiler/src/AST/Expr/Block.cpp new file mode 100644 index 0000000..0bbe462 --- /dev/null +++ b/compiler/src/AST/Expr/Block.cpp @@ -0,0 +1,25 @@ +#include "AST/Expr/Block.h" +#include "AST/Base.h" +#include "AST/Def.h" +#include "Utils.h" +#include +#include + +namespace plsm { + +boost::json::value ast::BlockExpr::toJson() { + return { + {"@type", "BlockExpr"}, + {"stmts", utils::mapToJson(stmts)}, + {"result", result->toJson()}, + }; +} + +std::unique_ptr +ast::BlockExpr::fromJson(boost::json::value json) { + auto stmts = fromJsonVector(json, "stmts"); + auto result = fromJsonProperty(json, "result"); + return std::make_unique(ast::Location::json(), stmts, result); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/Call.cpp b/compiler/src/AST/Expr/Call.cpp new file mode 100644 index 0000000..8661951 --- /dev/null +++ b/compiler/src/AST/Expr/Call.cpp @@ -0,0 +1,22 @@ +#include "AST/Expr/Call.h" +#include "AST/Def.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::CallExpr::toJson() { + return { + {"@type", "CallExpr"}, + {"callee", callee->toJson()}, + {"args", utils::mapToJson(args)}, + }; +} + +std::unique_ptr +ast::CallExpr::fromJson(boost::json::value json) { + auto callee = fromJsonProperty(json, "callee"); + auto args = fromJsonVector(json, "args"); + return std::make_unique(ast::Location::json(), callee, args); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/Closure.cpp b/compiler/src/AST/Expr/Closure.cpp new file mode 100644 index 0000000..8d3f26a --- /dev/null +++ b/compiler/src/AST/Expr/Closure.cpp @@ -0,0 +1,20 @@ +#include "AST/Def.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::Closure::toJson() { + return { + {"@type", "Closure"}, + {"args", utils::mapToJson(args)}, + {"body", body->toJson()}, + }; +} + +std::unique_ptr ast::Closure::fromJson(boost::json::value json) { + auto args = fromJsonVector(json, "args"); + auto body = fromJsonProperty(json, "body"); + return std::make_unique(ast::Location::json(), args, body); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/Identifier.cpp b/compiler/src/AST/Expr/Identifier.cpp new file mode 100644 index 0000000..8ea1fb8 --- /dev/null +++ b/compiler/src/AST/Expr/Identifier.cpp @@ -0,0 +1,19 @@ +#include "AST/Def.h" +#include "AST/Expr/Identifier.h" + +namespace plsm { + +boost::json::value ast::Identifier::toJson() { + return { + {"@type", "Identifier"}, + {"name", name}, + }; +} + +std::unique_ptr +ast::Identifier::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + return std::make_unique(ast::Location::json(), name); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/PropExpr.cpp b/compiler/src/AST/Expr/PropExpr.cpp new file mode 100644 index 0000000..2cccd61 --- /dev/null +++ b/compiler/src/AST/Expr/PropExpr.cpp @@ -0,0 +1,21 @@ +#include "AST/Def.h" +#include + +namespace plsm { + +boost::json::value ast::PropExpr::toJson() { + return { + {"@type", "PropExpr"}, + {"expr", expr->toJson()}, + {"property", property}, + }; +} + +std::unique_ptr +ast::PropExpr::fromJson(boost::json::value json) { + auto expr = fromJsonProperty(json, "expr"); + auto property = getJsonValue(json, "property"); + return std::make_unique(ast::Location::json(), expr, property); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/Tuple.cpp b/compiler/src/AST/Expr/Tuple.cpp new file mode 100644 index 0000000..04ef18f --- /dev/null +++ b/compiler/src/AST/Expr/Tuple.cpp @@ -0,0 +1,18 @@ +#include "AST/Def.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::Tuple::toJson() { + return { + {"@type", "Tuple"}, + {"values", utils::mapToJson(values)}, + }; +} + +std::unique_ptr ast::Tuple::fromJson(boost::json::value json) { + auto values = fromJsonVector(json, "values"); + return std::make_unique(ast::Location::json(), values); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/UnaryExpr.cpp b/compiler/src/AST/Expr/UnaryExpr.cpp new file mode 100644 index 0000000..0242754 --- /dev/null +++ b/compiler/src/AST/Expr/UnaryExpr.cpp @@ -0,0 +1,22 @@ +#include "AST/Def.h" +#include "AST/Expr/UnaryExpr.h" +#include + +namespace plsm { + +boost::json::value ast::UnaryExpr::toJson() { + return { + {"@type", "UnaryExpr"}, + {"op", op}, + {"expr", expr->toJson()}, + }; +} + +std::unique_ptr +ast::UnaryExpr::fromJson(boost::json::value json) { + auto op = getJsonValue(json, "op"); + auto expr = fromJsonProperty(json, "expr"); + return std::make_unique(ast::Location::json(), op, expr); +} + +} // namespace plsm diff --git a/compiler/src/AST/Expr/Value.cpp b/compiler/src/AST/Expr/Value.cpp new file mode 100644 index 0000000..849d26c --- /dev/null +++ b/compiler/src/AST/Expr/Value.cpp @@ -0,0 +1,29 @@ +#include "AST/Def.h" +#include + +namespace plsm { + +boost::json::value ast::NullValue::toJson() { return nullptr; } + +std::unique_ptr +ast::NullValue::fromJson(boost::json::value json) { + return std::make_unique(ast::Location::json()); +} + +boost::json::value ast::IntValue::toJson() { return value; } + +std::unique_ptr +ast::IntValue::fromJson(boost::json::value json) { + return std::make_unique(ast::Location::json(), + json.as_int64()); +} + +boost::json::value ast::FloatValue::toJson() { return value; } + +std::unique_ptr +ast::FloatValue::fromJson(boost::json::value json) { + return std::make_unique(ast::Location::json(), + json.as_double()); +} + +} // namespace plsm diff --git a/compiler/src/AST/Module/Import.cpp b/compiler/src/AST/Module/Import.cpp new file mode 100644 index 0000000..0d0f8a6 --- /dev/null +++ b/compiler/src/AST/Module/Import.cpp @@ -0,0 +1,19 @@ +#include "AST/Def.h" +#include + +namespace plsm { + +boost::json::value ast::Import::toJson() { + return { + {"@type", "Import"}, + {"moduleName", moduleName} + }; +} + +std::unique_ptr +ast::Import::fromJson(boost::json::value json) { + auto moduleName = getJsonValue(json, "moduleName"); + return std::make_unique(ast::Location::json(), moduleName); +} + +} // namespace plsm diff --git a/compiler/src/AST/Module/Module.cpp b/compiler/src/AST/Module/Module.cpp new file mode 100644 index 0000000..590d890 --- /dev/null +++ b/compiler/src/AST/Module/Module.cpp @@ -0,0 +1,22 @@ +#include "AST/Def.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::Module::toJson() { + return { + {"@type", "Module"}, + {"name", name}, + {"imports", utils::mapToJson(imports)}, + {"stmts", utils::mapToJson(stmts)}, + }; +} + +std::unique_ptr ast::Module::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto imports = fromJsonVector(json, "imports"); + auto stmts = fromJsonVector(json, "stmts"); + return std::make_unique(ast::Location::json(), name, imports, stmts); +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/ExprStmt.cpp b/compiler/src/AST/Stmt/ExprStmt.cpp new file mode 100644 index 0000000..74d183c --- /dev/null +++ b/compiler/src/AST/Stmt/ExprStmt.cpp @@ -0,0 +1,16 @@ +#include "AST/Stmt/ExprStmt.h" +#include "AST/Def.h" + +namespace plsm { + +boost::json::value ast::ExprStmt::toJson() { + return {{"@type", "ExprStmt"}, {"expr", expr->toJson()}}; +} + +std::unique_ptr +ast::ExprStmt::fromJson(boost::json::value json) { + auto expr = fromJsonProperty(json, "expr"); + return std::make_unique(ast::Location::json(), expr); +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/FnDef.cpp b/compiler/src/AST/Stmt/FnDef.cpp new file mode 100644 index 0000000..deea330 --- /dev/null +++ b/compiler/src/AST/Stmt/FnDef.cpp @@ -0,0 +1,39 @@ +#include "AST/Def.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::FnArg::toJson() { + return { + {"@type", "FnArg"}, + {"name", name}, + {"type", type->toJson()}, + }; +} + +std::unique_ptr ast::FnArg::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto type = fromJsonProperty(json, "type"); + return std::make_unique(ast::Location::json(), name, type); +} + +boost::json::value ast::FnDef::toJson() { + return { + {"@type", "FnDef"}, + {"name", name}, + {"args", utils::mapToJson(args)}, + {"returnType", returnType->toJson()}, + {"body", body->toJson()}, + }; +} + +std::unique_ptr ast::FnDef::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto args = fromJsonVector(json, "args"); + auto returnType = fromJsonProperty(json, "returnType"); + auto body = fromJsonProperty(json, "body"); + return std::make_unique(ast::Location::json(), name, args, + returnType, body); +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/TraitAlias.cpp b/compiler/src/AST/Stmt/TraitAlias.cpp new file mode 100644 index 0000000..25ee489 --- /dev/null +++ b/compiler/src/AST/Stmt/TraitAlias.cpp @@ -0,0 +1,22 @@ +#include "AST/Stmt/TraitAlias.h" +#include "AST/Def.h" + +namespace plsm { + +boost::json::value ast::TraitAlias::toJson() { + return { + {"@type", "TraitAlias"}, + {"alias", alias}, + {"aliased", aliased}, + }; +} + +std::unique_ptr +ast::TraitAlias::fromJson(boost::json::value json) { + auto alias = getJsonValue(json, "alias"); + auto aliased = getJsonValue(json, "aliased"); + return std::make_unique(ast::Location::json(), alias, + aliased); +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/TraitDef.cpp b/compiler/src/AST/Stmt/TraitDef.cpp new file mode 100644 index 0000000..fecb378 --- /dev/null +++ b/compiler/src/AST/Stmt/TraitDef.cpp @@ -0,0 +1,23 @@ +#include "AST/Def.h" +#include "AST/Stmt/FnDef.h" +#include "AST/Stmt/TraitDef.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::TraitDef::toJson() { + return { + {"@type", "TraitDef"}, + {"name", name}, + {"traits", utils::mapToJson(traits)}, + }; +} + +std::unique_ptr +ast::TraitDef::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto traits = fromJsonVector(json, "traits"); + return std::make_unique(ast::Location::json(), name, traits); +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/TypeAlias.cpp b/compiler/src/AST/Stmt/TypeAlias.cpp new file mode 100644 index 0000000..45c0a06 --- /dev/null +++ b/compiler/src/AST/Stmt/TypeAlias.cpp @@ -0,0 +1,18 @@ +#include "AST/Def.h" + +namespace plsm { + +boost::json::value ast::TypeAlias::toJson() { + return { + {"@type", "TypeAlias"}, + {"alias", alias}, + {"type", type->toJson()}, + }; +} + +std::unique_ptr +ast::TypeAlias::fromJson(boost::json::value json) { + return nullptr; +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/TypeDef.cpp b/compiler/src/AST/Stmt/TypeDef.cpp new file mode 100644 index 0000000..19f76ef --- /dev/null +++ b/compiler/src/AST/Stmt/TypeDef.cpp @@ -0,0 +1,25 @@ +#include "AST/Def.h" +#include "AST/Stmt/FnDef.h" +#include "AST/Stmt/TypeDef.h" +#include "Utils.h" +#include + +namespace plsm { + +boost::json::value ast::TypeDef::toJson() { + return { + {"@type", "TypeDef"}, + {"name", name}, + {"attrs", utils::mapToJson(attrs)}, + {"members", utils::mapToJson(members)}, + }; +} + +std::unique_ptr ast::TypeDef::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto attrs = fromJsonVector(json, "attrs"); + auto members = fromJsonVector(json, "members"); + return std::make_unique(ast::Location::json(), name, attrs, members); +} + +} // namespace plsm diff --git a/compiler/src/AST/Stmt/ValDecl.cpp b/compiler/src/AST/Stmt/ValDecl.cpp new file mode 100644 index 0000000..c2b3934 --- /dev/null +++ b/compiler/src/AST/Stmt/ValDecl.cpp @@ -0,0 +1,21 @@ +#include "AST/Def.h" + +namespace plsm { + +boost::json::value ast::ValDecl::toJson() { + return { + {"@type", "ValDecl"}, + {"name", name}, + {"type", type->toJson()}, + {"value", value->toJson()}, + }; +} + +std::unique_ptr ast::ValDecl::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto type = fromJsonProperty(json, "type"); + auto value = fromJsonProperty(json, "value"); + return std::make_unique(ast::Location::json(), name, type, value); +} + +} // namespace plsm diff --git a/compiler/src/AST/Type/Closure.cpp b/compiler/src/AST/Type/Closure.cpp new file mode 100644 index 0000000..53cf414 --- /dev/null +++ b/compiler/src/AST/Type/Closure.cpp @@ -0,0 +1,21 @@ +#include "AST/Def.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::ClosureType::toJson() { + return { + {"@type", "ClosureType"}, + {"from", utils::mapToJson(from)}, + {"to", to->toJson()}, + }; +} + +std::unique_ptr +ast::ClosureType::fromJson(boost::json::value json) { + auto from = fromJsonVector(json, "from"); + auto to = fromJsonProperty(json, "to"); + return std::make_unique(ast::Location::json(), from, to); +} + +} // namespace plsm diff --git a/compiler/src/AST/Type/Generic.cpp b/compiler/src/AST/Type/Generic.cpp new file mode 100644 index 0000000..5b9bd06 --- /dev/null +++ b/compiler/src/AST/Type/Generic.cpp @@ -0,0 +1,22 @@ +#include "AST/Def.h" +#include "AST/Type/Generic.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::GenericType::toJson() { + return { + {"@type", "GenericType"}, + {"name", name}, + {"types", utils::mapToJson(types)}, + }; +} + +std::unique_ptr +ast::GenericType::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + auto types = fromJsonVector(json, "types"); + return std::make_unique(ast::Location::json(), name, types); +} + +} // namespace plsm diff --git a/compiler/src/AST/Type/Named.cpp b/compiler/src/AST/Type/Named.cpp new file mode 100644 index 0000000..04b57d3 --- /dev/null +++ b/compiler/src/AST/Type/Named.cpp @@ -0,0 +1,19 @@ +#include "AST/Def.h" +#include "AST/Type/Named.h" + +namespace plsm { + +boost::json::value ast::NamedType::toJson() { + return { + {"@type", "NamedType"}, + {"name", name}, + }; +} + +std::unique_ptr +ast::NamedType::fromJson(boost::json::value json) { + auto name = getJsonValue(json, "name"); + return std::make_unique(ast::Location::json(), name); +} + +} // namespace plsm diff --git a/compiler/src/AST/Type/Tuple.cpp b/compiler/src/AST/Type/Tuple.cpp new file mode 100644 index 0000000..2d60bb1 --- /dev/null +++ b/compiler/src/AST/Type/Tuple.cpp @@ -0,0 +1,20 @@ +#include "AST/Def.h" +#include "AST/Type/Tuple.h" +#include "Utils.h" + +namespace plsm { + +boost::json::value ast::TupleType::toJson() { + return { + {"@type", "TupleType"}, + {"types", utils::mapToJson(types)}, + }; +} + +std::unique_ptr +ast::TupleType::fromJson(boost::json::value json) { + auto types = fromJsonVector(json, "types"); + return std::make_unique(ast::Location::json(), types); +} + +} // namespace plsm diff --git a/compiler/src/Parser.cpp b/compiler/src/Parser.cpp index ea8ead7..f0bbf6d 100644 --- a/compiler/src/Parser.cpp +++ b/compiler/src/Parser.cpp @@ -1,11 +1,16 @@ #include "Parser.h" -#include "plsmBaseVisitor.h" +#include "AST/Def.h" +#include #include -class ErrorListener : public antlr4::BaseErrorListener -{ +#include "AST/Module/Module.h" +#include "plsmBaseVisitor.h" +#include "plsmLexer.h" +#include "plsmParser.h" + +class ErrorListener : public antlr4::BaseErrorListener { std::string file; std::string *error; @@ -13,493 +18,453 @@ public: ErrorListener(const std::string &file, std::string *error) : file(file), error(error) {} - virtual void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, size_t charPositionInLine, - const std::string &msg, std::exception_ptr e) override - { + virtual void syntaxError(antlr4::Recognizer *recognizer, + antlr4::Token *offendingSymbol, size_t line, + size_t charPositionInLine, const std::string &msg, + std::exception_ptr e) override { std::stringstream ss; ss << file << ": line " << line << ":" << charPositionInLine << ": " << msg; *error = ss.str(); } }; -namespace plsm -{ - class Visitor : public plsmBaseVisitor - { - private: - const std::string file; +namespace plsm { - public: - Visitor(const std::string &file) : file(file) {} +class Visitor : public plsmBaseVisitor { +private: + const std::string file; - inline ast::Location loc(antlr4::ParserRuleContext *ctx) - { - return ast::Location( - file, - std::pair( - ctx->getStart()->getLine(), - ctx->getStart()->getCharPositionInLine()), - std::pair( - ctx->getStop()->getLine(), - ctx->getStop()->getCharPositionInLine())); +public: + Visitor(const std::string &file) : file(file) {} + + inline ast::Location loc(antlr4::ParserRuleContext *ctx) { + return ast::Location( + file, + std::pair(ctx->getStart()->getLine(), + ctx->getStart()->getCharPositionInLine()), + std::pair(ctx->getStop()->getLine(), + ctx->getStop()->getCharPositionInLine())); + } + + template inline T visitT(antlr4::tree::ParseTree *ctx) { + return std::any_cast(visit(ctx)); + } + + template + inline std::unique_ptr visitU(antlr4::tree::ParseTree *ctx) { + return std::unique_ptr(visitT(ctx)); + } + + template + inline std::vector> visitVU(antlr4::tree::ParseTree *ctx) { + std::vector> res; + for (auto &el : visitT>(ctx)) + res.push_back(std::unique_ptr(el)); + return res; + } + + virtual std::any visitModule(plsmParser::ModuleContext *ctx) override { + auto name = ctx->identifier()->getText(); + + std::vector> imports; + for (auto &import : ctx->moduleImport()) + imports.push_back(visitU(import)); + + std::vector> stmts; + for (auto &stmt : ctx->moduleStmt()) + stmts.push_back(visitU(stmt)); + + return std::any(new ast::Module(loc(ctx), name, imports, stmts)); + } + + virtual std::any + visitModuleImport(plsmParser::ModuleImportContext *ctx) override { + return std::any( + new ast::Import(loc(ctx), visitT(ctx->importName()))); + } + + virtual std::any + visitImportName(plsmParser::ImportNameContext *ctx) override { + auto name = ctx->identifier(0)->getText(); + + for (size_t i = 1; i < ctx->identifier().size(); i++) + name = name + "/" + ctx->identifier(i)->getText(); + + return std::any(name); + } + + virtual std::any + visitModuleStmt(plsmParser::ModuleStmtContext *ctx) override { + ast::Stmt *stmt; + + if (ctx->let()) + stmt = (ast::Stmt *)visitT(ctx->let()); + if (ctx->fnDecl()) + stmt = (ast::Stmt *)visitT(ctx->fnDecl()); + if (ctx->fnDef()) + stmt = (ast::Stmt *)visitT(ctx->fnDef()); + if (ctx->traitDef()) + stmt = (ast::Stmt *)visitT(ctx->traitDef()); + if (ctx->typeDef()) + stmt = (ast::Stmt *)visitT(ctx->typeDef()); + + return std::any(stmt); + } + + virtual std::any visitTraitDef(plsmParser::TraitDefContext *ctx) override { + auto name = ctx->identifier(0)->getText(); + + if (ctx->identifier(1)) { + auto aliased = ctx->identifier(1)->getText(); + return std::any( + (ast::Stmt *)new ast::TraitAlias(loc(ctx), name, aliased)); } - template - inline T visitT(antlr4::tree::ParseTree *ctx) - { - return std::any_cast(visit(ctx)); + std::vector> fns; + for (auto &decl : ctx->fnDecl()) + fns.push_back(visitU(decl)); + + return std::any((ast::Stmt *)new ast::TraitDef(loc(ctx), name, fns)); + } + + virtual std::any visitTypeDef(plsmParser::TypeDefContext *ctx) override { + auto name = ctx->identifier()->getText(); + + if (ctx->type()) { + auto gen = visitU(ctx->type()); + return std::any((ast::Stmt *)new ast::TypeAlias(loc(ctx), name, gen)); } - template - inline std::unique_ptr visitU(antlr4::tree::ParseTree *ctx) - { - return std::unique_ptr(visitT(ctx)); + std::vector> attrs; + if (ctx->fnDefArgs()) + attrs = visitVU(ctx->fnDefArgs()); + + std::vector> members; + for (auto &def : ctx->fnDef()) + members.push_back(visitU(def)); + for (auto &decl : ctx->fnDecl()) + members.push_back(visitU(decl)); + + return std::any( + (ast::Stmt *)new ast::TypeDef(loc(ctx), name, attrs, members)); + } + + virtual std::any visitFnDef(plsmParser::FnDefContext *ctx) override { + auto name = ctx->identifier()->getText(); + + std::vector> args; + if (ctx->fnDefArgs()) + args = std::move(visitVU(ctx->fnDefArgs())); + + auto returnType = visitU(ctx->type()); + auto body = visitU(ctx->expr()); + + return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body)); + } + + virtual std::any visitFnDefArgs(plsmParser::FnDefArgsContext *ctx) override { + std::vector args; + + for (size_t i = 0; i < ctx->children.size(); i += 3) { + auto name = ctx->children[i]->getText(); + auto type = visitU(ctx->children[i + 1]); + args.push_back(new ast::FnArg(loc(ctx), name, type)); } - template - inline std::vector> visitVU(antlr4::tree::ParseTree *ctx) - { - std::vector> res; - for (auto &el : visitT>(ctx)) - res.push_back(std::unique_ptr(el)); - return res; + return std::any(args); + } + + virtual std::any visitFnDecl(plsmParser::FnDeclContext *ctx) override { + auto name = ctx->identifier()->getText(); + + std::vector> args; + if (ctx->fnDeclArgs()) + args = visitVU(ctx->fnDeclArgs()); + + auto returnType = visitU(ctx->type()); + auto body = std::unique_ptr(nullptr); + + return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body)); + } + + virtual std::any + visitFnDeclArgs(plsmParser::FnDeclArgsContext *ctx) override { + std::vector args; + + for (size_t i = 0; i < ctx->children.size(); i++) { + std::string name; + if (dynamic_cast(ctx->children[i])) + name = ctx->children[i++]->getText(); + + auto type = visitU(ctx->children[i++]); + + args.push_back(new ast::FnArg(loc(ctx), name, type)); } - virtual std::any visitModule(plsmParser::ModuleContext *ctx) override - { - auto name = ctx->identifier()->getText(); + return std::any(args); + } - std::vector> imports; - for (auto &import : ctx->moduleImport()) - imports.push_back(visitU(import)); + virtual std::any visitLet(plsmParser::LetContext *ctx) override { + auto name = ctx->identifier()->getText(); - std::vector> stmts; - for (auto &stmt : ctx->moduleStmt()) - stmts.push_back(visitU(stmt)); + std::unique_ptr type(nullptr); + if (ctx->type()) + type = visitU(ctx->type()); - return std::any(new ast::Module(loc(ctx), name, imports, stmts)); - } + auto expr = visitU(ctx->expr()); - virtual std::any visitModuleImport(plsmParser::ModuleImportContext *ctx) override - { - return std::any(new ast::Import(loc(ctx), visitT(ctx->importName()))); - } + return std::any(new ast::ValDecl(loc(ctx), name, type, expr)); + } - virtual std::any visitImportName(plsmParser::ImportNameContext *ctx) override - { - auto name = ctx->identifier(0)->getText(); + virtual std::any visitExprStmt(plsmParser::ExprStmtContext *ctx) override { + auto expr = visitU(ctx->expr()); + return std::any(new ast::ExprStmt(loc(ctx), expr)); + } - for (size_t i = 1; i < ctx->identifier().size(); i++) - name = name + "/" + ctx->identifier(i)->getText(); - - return std::any(name); - } - - virtual std::any visitModuleStmt(plsmParser::ModuleStmtContext *ctx) override - { - ast::Stmt *stmt; - - if (ctx->let()) - stmt = (ast::Stmt *)visitT(ctx->let()); - if (ctx->fnDecl()) - stmt = (ast::Stmt *)visitT(ctx->fnDecl()); - if (ctx->fnDef()) - stmt = (ast::Stmt *)visitT(ctx->fnDef()); - if (ctx->traitDef()) - stmt = (ast::Stmt *)visitT(ctx->traitDef()); - if (ctx->typeDef()) - stmt = (ast::Stmt *)visitT(ctx->typeDef()); - - return std::any(stmt); - } - - virtual std::any visitTraitDef(plsmParser::TraitDefContext *ctx) override - { - auto name = ctx->identifier(0)->getText(); - - if (ctx->identifier(1)) - { - auto aliased = ctx->identifier(1)->getText(); - return std::any((ast::Stmt *)new ast::TraitAlias(loc(ctx), name, aliased)); - } - - std::vector> fns; - for (auto &decl : ctx->fnDecl()) - fns.push_back(visitU(decl)); - - return std::any((ast::Stmt *)new ast::TraitDef(loc(ctx), name, fns)); - } - - virtual std::any visitTypeDef(plsmParser::TypeDefContext *ctx) override - { - auto name = ctx->identifier()->getText(); + virtual std::any visitType1(plsmParser::Type1Context *ctx) override { + if (ctx->type0()) + return visit(ctx->type0()); + if (ctx->children[0]->getText() == "(") { if (ctx->type()) - { - auto gen = visitU(ctx->type()); - return std::any((ast::Stmt *)new ast::TypeAlias(loc(ctx), name, gen)); + return visit(ctx->type()); + + if (ctx->tupleTypeList()) { + auto types = visitVU(ctx->tupleTypeList()); + return std::any((ast::Type *)new ast::TupleType(loc(ctx), types)); } - - std::vector> attrs; - if (ctx->fnDefArgs()) - attrs = visitVU(ctx->fnDefArgs()); - - std::vector> members; - for (auto &def : ctx->fnDef()) - members.push_back(visitU(def)); - for (auto &decl : ctx->fnDecl()) - members.push_back(visitU(decl)); - - return std::any((ast::Stmt *)new ast::TypeDef(loc(ctx), name, attrs, members)); } - virtual std::any visitFnDef(plsmParser::FnDefContext *ctx) override - { - auto name = ctx->identifier()->getText(); - - std::vector> args; - if (ctx->fnDefArgs()) - args = std::move(visitVU(ctx->fnDefArgs())); + if (ctx->children[0]->getText() == "[") { + std::vector> args; + if (ctx->typeList()) + args = visitVU(ctx->typeList()); auto returnType = visitU(ctx->type()); + + return std::any( + (ast::Type *)new ast::ClosureType(loc(ctx), args, returnType)); + } + + throw std::logic_error("type2 not implemented"); + } + + virtual std::any visitType0(plsmParser::Type0Context *ctx) override { + auto name = ctx->identifier()->getText(); + + if (ctx->typeList()) { + auto types = visitVU(ctx->typeList()); + return std::any((ast::Type *)new ast::GenericType(loc(ctx), name, types)); + } + + return std::any((ast::Type *)new ast::NamedType(loc(ctx), name)); + } + + virtual std::any + visitTupleTypeList(plsmParser::TupleTypeListContext *ctx) override { + std::vector types; + for (auto &type : ctx->type()) + types.push_back(visitT(type)); + + return std::any(types); + } + + virtual std::any visitTypeList(plsmParser::TypeListContext *ctx) override { + std::vector types; + for (auto &type : ctx->type()) + types.push_back(visitT(type)); + + return std::any(types); + } + + virtual std::any visitExpr3(plsmParser::Expr3Context *ctx) override { + if (ctx->expr2()) + return visit(ctx->expr2()); + + // closure + if (ctx->children[0]->getText() == "[") { + std::vector> args; + if (ctx->fnDefArgs()) + args = visitVU(ctx->fnDefArgs()); + auto body = visitU(ctx->expr()); - return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body)); + return std::any((ast::Expr *)new ast::Closure(loc(ctx), args, body)); } - virtual std::any visitFnDefArgs(plsmParser::FnDefArgsContext *ctx) override - { - std::vector args; + // block + if (ctx->children[0]->getText() == "{") { + std::vector> stmts; + for (auto &stmt : ctx->blockStmt()) + stmts.push_back(visitU(stmt)); - for (size_t i = 0; i < ctx->children.size(); i += 3) - { - auto name = ctx->children[i]->getText(); - auto type = visitU(ctx->children[i + 1]); - args.push_back(new ast::FnArg(loc(ctx), name, type)); - } + auto result = visitU(ctx->expr()); - return std::any(args); + return std::any((ast::Expr *)new ast::BlockExpr(loc(ctx), stmts, result)); } - virtual std::any visitFnDecl(plsmParser::FnDeclContext *ctx) override - { - auto name = ctx->identifier()->getText(); - - std::vector> args; - if (ctx->fnDeclArgs()) - args = visitVU(ctx->fnDeclArgs()); - - auto returnType = visitU(ctx->type()); - auto body = std::unique_ptr(nullptr); - - return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body)); - } - - virtual std::any visitFnDeclArgs(plsmParser::FnDeclArgsContext *ctx) override - { - std::vector args; - - for (size_t i = 0; i < ctx->children.size(); i++) - { - std::string name; - if (dynamic_cast(ctx->children[i])) - name = ctx->children[i++]->getText(); - - auto type = visitU(ctx->children[i++]); - - args.push_back(new ast::FnArg(loc(ctx), name, type)); - } - - return std::any(args); - } - - virtual std::any visitLet(plsmParser::LetContext *ctx) override - { - auto name = ctx->identifier()->getText(); - - std::unique_ptr type(nullptr); - if (ctx->type()) - type = visitU(ctx->type()); - - auto expr = visitU(ctx->expr()); - - return std::any(new ast::ValDecl(loc(ctx), name, type, expr)); - } - - virtual std::any visitExprStmt(plsmParser::ExprStmtContext *ctx) override - { - auto expr = visitU(ctx->expr()); - return std::any(new ast::ExprStmt(loc(ctx), expr)); - } - - virtual std::any visitType1(plsmParser::Type1Context *ctx) override - { - if (ctx->type0()) - return visit(ctx->type0()); - - if (ctx->children[0]->getText() == "(") - { - if (ctx->type()) - return visit(ctx->type()); - - if (ctx->tupleTypeList()) - { - auto types = visitVU(ctx->tupleTypeList()); - return std::any((ast::Type *)new ast::TupleType(loc(ctx), types)); - } - } - - if (ctx->children[0]->getText() == "[") - { - std::vector> args; - if (ctx->typeList()) - args = visitVU(ctx->typeList()); - - auto returnType = visitU(ctx->type()); - - return std::any((ast::Type *)new ast::ClosureType(loc(ctx), args, returnType)); - } - - throw std::logic_error("type2 not implemented"); - } - - virtual std::any visitType0(plsmParser::Type0Context *ctx) override - { - auto name = ctx->identifier()->getText(); - - if (ctx->typeList()) - { - auto types = visitVU(ctx->typeList()); - return std::any((ast::Type *)new ast::GenericType(loc(ctx), name, types)); - } - - return std::any((ast::Type *)new ast::NamedType(loc(ctx), name)); - } - - virtual std::any visitTupleTypeList(plsmParser::TupleTypeListContext *ctx) override - { - std::vector types; - for (auto &type : ctx->type()) - types.push_back(visitT(type)); - - return std::any(types); - } - - virtual std::any visitTypeList(plsmParser::TypeListContext *ctx) override - { - std::vector types; - for (auto &type : ctx->type()) - types.push_back(visitT(type)); - - return std::any(types); - } - - virtual std::any visitExpr3(plsmParser::Expr3Context *ctx) override - { - if (ctx->expr2()) - return visit(ctx->expr2()); - - // closure - if (ctx->children[0]->getText() == "[") - { - std::vector args; - if (ctx->identifierList()) - args = visitT>(ctx->identifierList()); - - auto body = visitU(ctx->expr()); - - return std::any((ast::Expr *)new ast::Closure(loc(ctx), args, body)); - } - - // block - if (ctx->children[0]->getText() == "{") - { - std::vector> stmts; - for (auto &stmt : ctx->blockStmt()) - stmts.push_back(visitU(stmt)); - - auto result = visitU(ctx->expr()); - - return std::any((ast::Expr *)new ast::BlockExpr(loc(ctx), stmts, result)); - } - - throw std::logic_error("expr3 not implemented"); - } - - virtual std::any visitExpr2(plsmParser::Expr2Context *ctx) override - { - if (ctx->expr2()) - { - auto left = visitU(ctx->expr2()); - auto op = ctx->operator_()->getText(); - auto right = visitU(ctx->expr1()); - return std::any((ast::Expr *)new ast::BinExpr(loc(ctx), left, op, right)); - } - - return visit(ctx->expr1()); - } - - virtual std::any visitExpr1(plsmParser::Expr1Context *ctx) override - { - if (ctx->operator_()) - { - auto op = ctx->operator_()->getText(); - auto expr = visitU(ctx->expr0()); - return std::any((ast::Expr *)new ast::UnaryExpr(loc(ctx), op, expr)); - } - - return visit(ctx->expr0()); - } - - virtual std::any visitExpr0(plsmParser::Expr0Context *ctx) override - { - if (ctx->literal()) - return visit(ctx->literal()); - - if (ctx->expr()) - { - auto expr = visitU(ctx->expr()); - return std::any((ast::Expr *)new ast::PrefExpr(loc(ctx), expr)); - } - - if (ctx->expr0()) - { - auto expr = visitU(ctx->expr0()); - - // property accessor - if (ctx->identifier()) - { - auto name = ctx->identifier()->getText(); - return std::any((ast::Expr *)new ast::PropExpr(loc(ctx), expr, name)); - } - - // function/closure call - std::vector> args; - if (ctx->exprList()) - args = visitVU(ctx->exprList()); - - return std::any((ast::Expr *)new ast::CallExpr(loc(ctx), expr, args)); - } - - // tuple - if (ctx->tupleExprList()) - { - auto values = visitVU(ctx->tupleExprList()); - return std::any((ast::Expr *)new ast::Tuple(loc(ctx), values)); - } - - // identifier - if (ctx->identifier()) - { - auto name = ctx->identifier()->getText(); - return std::any((ast::Expr *)new ast::Identifier(loc(ctx), name)); - } - - throw std::logic_error("expr0 not implemented"); - } - - virtual std::any visitBlockStmt(plsmParser::BlockStmtContext *ctx) override - { - ast::Stmt *stmt; - - if (ctx->let()) - stmt = (ast::Stmt *)visitT(ctx->let()); - if (ctx->exprStmt()) - stmt = (ast::Stmt *)visitT(ctx->exprStmt()); - if (ctx->fnDef()) - stmt = (ast::Stmt *)visitT(ctx->fnDef()); - - return std::any(stmt); - } - - virtual std::any visitTupleExprList(plsmParser::TupleExprListContext *ctx) override - { - std::vector exprs; - for (auto &expr : ctx->expr()) - exprs.push_back(visitT(expr)); - - return std::any(exprs); - } - - virtual std::any visitExprList(plsmParser::ExprListContext *ctx) override - { - std::vector exprs; - for (auto &expr : ctx->expr()) - exprs.push_back(visitT(expr)); - - return std::any(exprs); - } - - virtual std::any visitIdentifierList(plsmParser::IdentifierListContext *ctx) override - { - std::vector identifiers; - for (auto &identifier : ctx->identifier()) - identifiers.push_back(visitT(identifier)); - - return std::any(identifiers); - } - - virtual std::any visitLiteral(plsmParser::LiteralContext *ctx) override - { - if (ctx->NULL_) - return std::any((ast::Expr *)new ast::NullValue(loc(ctx))); - - if (ctx->INT_LIT()) - { - auto text = ctx->INT_LIT()->getText(); - - int64_t value; - - if (!text.rfind("0x", 0)) - value = std::strtol(text.substr(2).data(), NULL, 16); - - if (!text.rfind("0o", 0)) - value = std::strtol(text.substr(2).data(), NULL, 8); - - if (!text.rfind("0b", 0)) - value = std::strtol(text.substr(2).data(), NULL, 2); - - return std::any((ast::Expr *)new ast::IntValue(loc(ctx), value)); - } - - if (ctx->FLOAT_LIT()) - { - auto text = ctx->FLOAT_LIT()->getText(); - if (text.at(text.size() - 1) == '.') - text += "0"; - - double value = std::strtod(text.data(), NULL); - return std::any((ast::Expr *)new ast::FloatValue(loc(ctx), value)); - } - - throw std::logic_error("literal not implemented"); - } - }; - - std::unique_ptr parse(const std::string &file, const std::string &input) - { - auto istream = antlr4::ANTLRInputStream(input); - auto lexer = plsmLexer(&istream); - auto tokens = antlr4::CommonTokenStream(&lexer); - auto parser = plsmParser(&tokens); - - std::string error; - ErrorListener listener(file, &error); - parser.removeErrorListeners(); - parser.addErrorListener(&listener); - - auto tree = parser.module(); - - if (error.size()) - throw std::runtime_error(error); - - auto module = std::any_cast(Visitor(file).visitModule(tree)); - return std::unique_ptr(module); + throw std::logic_error("expr3 not implemented"); } + + virtual std::any visitExpr2(plsmParser::Expr2Context *ctx) override { + if (ctx->expr2()) { + auto left = visitU(ctx->expr2()); + auto op = ctx->operator_()->getText(); + auto right = visitU(ctx->expr1()); + return std::any((ast::Expr *)new ast::BinExpr(loc(ctx), left, op, right)); + } + + return visit(ctx->expr1()); + } + + virtual std::any visitExpr1(plsmParser::Expr1Context *ctx) override { + if (ctx->operator_()) { + auto op = ctx->operator_()->getText(); + auto expr = visitU(ctx->expr0()); + return std::any((ast::Expr *)new ast::UnaryExpr(loc(ctx), op, expr)); + } + + return visit(ctx->expr0()); + } + + virtual std::any visitExpr0(plsmParser::Expr0Context *ctx) override { + if (ctx->literal()) + return visit(ctx->literal()); + + if (ctx->expr()) { + auto expr = visitU(ctx->expr()); + return std::any((ast::Expr *)new ast::PrefExpr(loc(ctx), expr)); + } + + if (ctx->expr0()) { + auto expr = visitU(ctx->expr0()); + + // property accessor + if (ctx->identifier()) { + auto name = ctx->identifier()->getText(); + return std::any((ast::Expr *)new ast::PropExpr(loc(ctx), expr, name)); + } + + // function/closure call + std::vector> args; + if (ctx->exprList()) + args = visitVU(ctx->exprList()); + + return std::any((ast::Expr *)new ast::CallExpr(loc(ctx), expr, args)); + } + + // tuple + if (ctx->tupleExprList()) { + auto values = visitVU(ctx->tupleExprList()); + return std::any((ast::Expr *)new ast::Tuple(loc(ctx), values)); + } + + // identifier + if (ctx->identifier()) { + auto name = ctx->identifier()->getText(); + return std::any((ast::Expr *)new ast::Identifier(loc(ctx), name)); + } + + throw std::logic_error("expr0 not implemented"); + } + + virtual std::any visitBlockStmt(plsmParser::BlockStmtContext *ctx) override { + ast::Stmt *stmt; + + if (ctx->let()) + stmt = (ast::Stmt *)visitT(ctx->let()); + if (ctx->exprStmt()) + stmt = (ast::Stmt *)visitT(ctx->exprStmt()); + if (ctx->fnDef()) + stmt = (ast::Stmt *)visitT(ctx->fnDef()); + + return std::any(stmt); + } + + virtual std::any + visitTupleExprList(plsmParser::TupleExprListContext *ctx) override { + std::vector exprs; + for (auto &expr : ctx->expr()) + exprs.push_back(visitT(expr)); + + return std::any(exprs); + } + + virtual std::any visitExprList(plsmParser::ExprListContext *ctx) override { + std::vector exprs; + for (auto &expr : ctx->expr()) + exprs.push_back(visitT(expr)); + + return std::any(exprs); + } + + virtual std::any + visitIdentifierList(plsmParser::IdentifierListContext *ctx) override { + std::vector identifiers; + for (auto &identifier : ctx->identifier()) + identifiers.push_back(visitT(identifier)); + + return std::any(identifiers); + } + + virtual std::any visitLiteral(plsmParser::LiteralContext *ctx) override { + if (ctx->NULL_) + return std::any((ast::Expr *)new ast::NullValue(loc(ctx))); + + if (ctx->INT_LIT()) { + auto text = ctx->INT_LIT()->getText(); + + int64_t value; + + if (!text.rfind("0x", 0)) + value = std::strtol(text.substr(2).data(), NULL, 16); + + else if (!text.rfind("0o", 0)) + value = std::strtol(text.substr(2).data(), NULL, 8); + + else if (!text.rfind("0b", 0)) + value = std::strtol(text.substr(2).data(), NULL, 2); + + else value = std::strtol(text.data(), NULL, 10); + + return std::any((ast::Expr *)new ast::IntValue(loc(ctx), value)); + } + + if (ctx->FLOAT_LIT()) { + auto text = ctx->FLOAT_LIT()->getText(); + + if (text.at(text.size() - 1) == '.') + text += "0"; + if (text.at(0) == '0') + text = "0" + text; + + double value = std::strtod(text.data(), NULL); + return std::any((ast::Expr *)new ast::FloatValue(loc(ctx), value)); + } + + throw std::logic_error("literal not implemented"); + } +}; + +std::unique_ptr parse(const std::string &file, + const std::string &input) { + auto istream = antlr4::ANTLRInputStream(input); + auto lexer = plsmLexer(&istream); + auto tokens = antlr4::CommonTokenStream(&lexer); + auto parser = plsmParser(&tokens); + + std::string error; + ErrorListener listener(file, &error); + parser.removeErrorListeners(); + parser.addErrorListener(&listener); + + auto tree = parser.module(); + + if (error.size()) + throw std::runtime_error(error); + + auto module = std::any_cast(Visitor(file).visitModule(tree)); + return std::unique_ptr(module); } -std::unique_ptr -adscript::parse(const std::string &file, const std::string &input) -{ - throw std::logic_error("adscript::parse not implemented"); -} +} // namespace plsm diff --git a/compiler/src/main.cpp b/compiler/src/main.cpp index a25bf61..2fd99da 100644 --- a/compiler/src/main.cpp +++ b/compiler/src/main.cpp @@ -30,6 +30,11 @@ int main(int argc, char *argv[]) try { auto module = plsm::parse(argv[1], input); + std::cout << module->toJsonString() << std::endl; + + std::cout << "\n\n"; + + std::cout << plsm::ast::Module::fromJson(module->toJson())->toJson() << std::endl; } catch (std::runtime_error &err) { diff --git a/compiler/thirdparty/antlr-4.13.1.zip b/compiler/thirdparty/antlr-4.13.1.zip new file mode 100644 index 0000000..a14091b Binary files /dev/null and b/compiler/thirdparty/antlr-4.13.1.zip differ