json serialization of ast

This commit is contained in:
Ludwig Lehnert 2024-03-23 12:31:49 +00:00
parent 49ee4ff42d
commit 385f2dd53e
58 changed files with 1779 additions and 915 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
build/
.cache
generated/

View File

@ -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

View File

@ -1,8 +0,0 @@
grammar adscript;
module:;
// TODO ;)
FN: 'fn';
TYPE: 'type';

View File

@ -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()

View File

@ -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

View File

@ -1,56 +1,128 @@
#pragma once
#include <utility>
#include <string>
#include <boost/json/serialize.hpp>
#include <exception>
#include <functional>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <boost/json.hpp>
#define LOC_ARG const Location &location
namespace ast
{
class Location
{
public:
Location(const std::string &file, std::pair<size_t, size_t> start, std::pair<size_t, size_t> end)
: file(file), start(start), end(end) {}
namespace plsm {
namespace ast {
const std::string file;
const std::pair<size_t, size_t> start, end;
};
class Location {
public:
Location(const std::string &file, std::pair<size_t, size_t> start,
std::pair<size_t, size_t> 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<size_t, size_t> start, end;
const Location location;
static Location json() { return Location("<json>", {-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; }
};
}
static std::unique_ptr<ASTNode> fromJson(boost::json::value json);
virtual bool isExpr() { return false; }
virtual bool isStmt() { return false; }
virtual bool isType() { return false; }
protected:
template <class CurrNode>
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 <class CurrNode, typename T>
static inline T getJsonValue(boost::json::value json, std::string property) {
auto prop = getJsonProperty<CurrNode>(json, property);
try {
return boost::json::value_to<T>(prop);
} catch (...) {
throw std::runtime_error("invalid value for property '" + property +
"' in " + typeid(CurrNode).name() +
"::fromJson");
}
}
template <class CurrNode, class SubNode>
static inline auto fromJsonProperty(boost::json::value json,
std::string property) {
return SubNode::fromJson(getJsonProperty<CurrNode>(json, property));
}
template <class CurrNode, class SubNode>
static inline auto fromJsonVector(boost::json::value json,
std::string property) {
auto arr = getJsonProperty<CurrNode>(json, property).as_array();
std::vector<std::unique_ptr<SubNode>> 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<Expr> 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<Stmt> 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<Type> fromJson(boost::json::value json);
virtual bool isType() override { return true; }
};
} // namespace ast
} // namespace plsm

View File

@ -1,45 +1,38 @@
#pragma once
#include "AST/Base.h"
#include <string>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
namespace ast
{
class BinExpr : public Expr
{
const std::string op;
const std::unique_ptr<Expr> left, right;
namespace plsm {
namespace ast {
public:
BinExpr(LOC_ARG, std::unique_ptr<Expr> &left, const std::string &op, std::unique_ptr<Expr> &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<Expr> 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<Expr> &left, const std::string &op,
std::unique_ptr<Expr> &right)
: Expr(location), left(std::move(left)), op(op), right(std::move(right)) {
}
class PrefExpr : public Expr
{
const std::unique_ptr<Expr> expr;
virtual boost::json::value toJson() override;
static std::unique_ptr<BinExpr> fromJson(boost::json::value json);
};
public:
PrefExpr(LOC_ARG, std::unique_ptr<Expr> &expr)
: Expr(location), expr(std::move(expr)) {}
class PrefExpr : public Expr {
const std::unique_ptr<Expr> expr;
virtual std::string str()
{
return (std::stringstream() << "PrefExpr("
<< "expr=" << expr->str()
<< ")")
.str();
}
};
}
public:
PrefExpr(LOC_ARG, std::unique_ptr<Expr> &expr)
: Expr(location), expr(std::move(expr)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<PrefExpr> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,38 +1,25 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <memory>
#include <sstream>
#include <vector>
namespace ast
{
class BlockExpr : public Expr
{
const std::vector<std::unique_ptr<Stmt>> stmts;
const std::unique_ptr<Expr> result;
namespace plsm {
namespace ast {
public:
BlockExpr(LOC_ARG, std::vector<std::unique_ptr<Stmt>> &stmts, std::unique_ptr<Expr> &result)
: Expr(location), stmts(std::move(stmts)), result(std::move(result)) {}
class BlockExpr : public Expr {
const std::vector<std::unique_ptr<Stmt>> stmts;
const std::unique_ptr<Expr> result;
virtual std::string str()
{
std::stringstream ss;
ss << "BlockExpr(";
public:
BlockExpr(LOC_ARG, std::vector<std::unique_ptr<Stmt>> &stmts,
std::unique_ptr<Expr> &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<BlockExpr> fromJson(boost::json::value json);
};
ss << "result=" << result->str();
ss << ")";
return ss.str();
}
};
}
} // namespace ast
} // namespace plsm

View File

@ -1,39 +1,25 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <memory>
#include <sstream>
#include <vector>
namespace ast
{
class CallExpr : public Expr
{
const std::unique_ptr<Expr> callee;
const std::vector<std::unique_ptr<Expr>> args;
namespace plsm {
namespace ast {
public:
CallExpr(LOC_ARG, std::unique_ptr<Expr> &callee, std::vector<std::unique_ptr<Expr>> &args)
: Expr(location), callee(std::move(callee)), args(std::move(args)) {}
class CallExpr : public Expr {
const std::unique_ptr<Expr> callee;
const std::vector<std::unique_ptr<Expr>> args;
virtual std::string str()
{
std::stringstream ss;
public:
CallExpr(LOC_ARG, std::unique_ptr<Expr> &callee,
std::vector<std::unique_ptr<Expr>> &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<CallExpr> 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();
}
};
}
} // namespace ast
} // namespace plsm

View File

@ -1,38 +1,25 @@
#pragma once
#include "AST/Base.h"
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include <memory>
namespace ast
{
class Closure : public Expr
{
const std::vector<std::string> args;
const std::unique_ptr<Expr> body;
namespace plsm {
namespace ast {
class FnArg;
public:
Closure(LOC_ARG, std::vector<std::string> &args, std::unique_ptr<Expr> &body)
: Expr(location), args(std::move(args)), body(std::move(body)) {}
class Closure : public Expr {
const std::vector<std::unique_ptr<FnArg>> args;
const std::unique_ptr<Expr> body;
virtual std::string str()
{
std::stringstream ss;
public:
Closure(LOC_ARG, std::vector<std::unique_ptr<FnArg>> &args, std::unique_ptr<Expr> &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();
}
};
}
virtual boost::json::value toJson() override;
static std::unique_ptr<Closure> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -3,19 +3,17 @@
#include "AST/Base.h"
#include <string>
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 + ")";
}
};
}
virtual boost::json::value toJson() override;
static std::unique_ptr<Identifier> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -2,26 +2,21 @@
#include "AST/Base.h"
#include <memory>
#include <sstream>
#include <string>
namespace ast
{
class PropExpr : public Expr
{
const std::unique_ptr<Expr> expr;
const std::string property;
namespace plsm {
namespace ast {
class PropExpr : public Expr {
const std::unique_ptr<Expr> expr;
const std::string property;
public:
PropExpr(LOC_ARG, std::unique_ptr<Expr> &expr, const std::string &property)
: Expr(location), expr(std::move(expr)), property(property) {}
public:
PropExpr(LOC_ARG, std::unique_ptr<Expr> &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();
}
};
}
virtual boost::json::value toJson() override;
static std::unique_ptr<PropExpr> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,17 +1,23 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <memory>
#include <sstream>
#include <vector>
namespace ast
{
class Tuple : public Expr
{
const std::vector<std::unique_ptr<Expr>> values;
namespace plsm {
namespace ast {
public:
Tuple(LOC_ARG, std::vector<std::unique_ptr<Expr>> &values)
: Expr(location), values(std::move(values)) {}
};
}
class Tuple : public Expr {
const std::vector<std::unique_ptr<Expr>> values;
public:
Tuple(LOC_ARG, std::vector<std::unique_ptr<Expr>> &values)
: Expr(location), values(std::move(values)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<Tuple> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,18 +1,23 @@
#pragma once
#include "AST/Base.h"
#include <string>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
namespace ast
{
class UnaryExpr : public Expr
{
const std::string op;
const std::unique_ptr<Expr> expr;
namespace plsm {
namespace ast {
class UnaryExpr : public Expr {
const std::string op;
const std::unique_ptr<Expr> expr;
public:
UnaryExpr(LOC_ARG, const std::string &op, std::unique_ptr<Expr> &expr)
: Expr(location), op(op), expr(std::move(expr)) {}
};
}
public:
UnaryExpr(LOC_ARG, const std::string &op, std::unique_ptr<Expr> &expr)
: Expr(location), op(op), expr(std::move(expr)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<UnaryExpr> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,31 +1,38 @@
#pragma once
#include "AST/Base.h"
#include <string>
#include <cstdint>
#include <cfloat>
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<NullValue> 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<IntValue> 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<FloatValue> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,16 +1,21 @@
#pragma once
#include "AST/Base.h"
#include <iomanip>
#include <sstream>
#include <string>
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) {}
};
}
public:
Import(LOC_ARG, const std::string &moduleName)
: ASTNode(location), moduleName(moduleName) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<Import> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,21 +1,30 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <cstddef>
#include <iomanip>
#include <memory>
#include <vector>
#include <sstream>
namespace ast
{
class Import;
namespace plsm {
namespace ast {
class Import;
class Module : public ASTNode
{
const std::string name;
const std::vector<std::unique_ptr<Import>> imports;
const std::vector<std::unique_ptr<Stmt>> stmts;
class Module : public ASTNode {
const std::string name;
const std::vector<std::unique_ptr<Import>> imports;
const std::vector<std::unique_ptr<Stmt>> stmts;
public:
Module(LOC_ARG, const std::string &name, std::vector<std::unique_ptr<Import>> &imports, std::vector<std::unique_ptr<Stmt>> &stmts)
: ASTNode(location), name(name), imports(std::move(imports)), stmts(std::move(stmts)) {}
};
}
public:
Module(LOC_ARG, const std::string &name,
std::vector<std::unique_ptr<Import>> &imports,
std::vector<std::unique_ptr<Stmt>> &stmts)
: ASTNode(location), name(name), imports(std::move(imports)),
stmts(std::move(stmts)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<Module> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -3,14 +3,17 @@
#include "AST/Base.h"
#include <memory>
namespace ast
{
class ExprStmt : public Stmt
{
const std::unique_ptr<Expr> expr;
namespace plsm {
namespace ast {
class ExprStmt : public Stmt {
const std::unique_ptr<Expr> expr;
public:
ExprStmt(LOC_ARG, std::unique_ptr<Expr> &expr)
: Stmt(location), expr(std::move(expr)) {}
};
}
public:
ExprStmt(LOC_ARG, std::unique_ptr<Expr> &expr)
: Stmt(location), expr(std::move(expr)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<ExprStmt> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,31 +1,41 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <string>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
namespace ast
{
class FnArg : public ASTNode
{
const std::string name;
const std::unique_ptr<Type> type;
namespace plsm {
namespace ast {
class FnArg : public ASTNode {
const std::string name;
const std::unique_ptr<Type> type;
public:
FnArg(LOC_ARG, const std::string &name, std::unique_ptr<Type> &type)
: ASTNode(location), name(name), type(std::move(type)) {}
};
public:
FnArg(LOC_ARG, const std::string &name, std::unique_ptr<Type> &type)
: ASTNode(location), name(name), type(std::move(type)) {}
class FnDef : public Stmt
{
const std::string name;
const std::vector<std::unique_ptr<FnArg>> args;
const std::unique_ptr<Type> returnType;
const std::unique_ptr<Expr> body;
virtual boost::json::value toJson() override;
static std::unique_ptr<FnArg> fromJson(boost::json::value json);
};
public:
FnDef(LOC_ARG, const std::string &name, std::vector<std::unique_ptr<FnArg>> &args, std::unique_ptr<Type> &returnType, std::unique_ptr<Expr> &body)
: Stmt(location), name(name), args(std::move(args)), returnType(std::move(returnType)), body(std::move(body)) {}
};
}
class FnDef : public Stmt {
const std::string name;
const std::vector<std::unique_ptr<FnArg>> args;
const std::unique_ptr<Type> returnType;
const std::unique_ptr<Expr> body;
public:
FnDef(LOC_ARG, const std::string &name,
std::vector<std::unique_ptr<FnArg>> &args,
std::unique_ptr<Type> &returnType, std::unique_ptr<Expr> &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<FnDef> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,19 +1,24 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <string>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
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) {}
};
}
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<TraitAlias> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,21 +1,26 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <string>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
namespace ast
{
class FnDef;
namespace plsm {
namespace ast {
class FnDef;
class TraitDef : public Stmt {
const std::string name;
const std::vector<std::unique_ptr<FnDef>> traits;
class TraitDef : public Stmt
{
const std::string name;
const std::vector<std::unique_ptr<FnDef>> traits;
public:
TraitDef(LOC_ARG, const std::string &name,
std::vector<std::unique_ptr<FnDef>> &traits)
: Stmt(location), name(name), traits(std::move(traits)) {}
public:
TraitDef(LOC_ARG, const std::string &name, std::vector<std::unique_ptr<FnDef>> &traits)
: Stmt(location), name(name), traits(std::move(traits)) {}
};
}
virtual boost::json::value toJson() override;
static std::unique_ptr<TraitDef> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,19 +1,24 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <string>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
namespace ast
{
class TypeAlias : public Stmt
{
const std::string alias;
const std::unique_ptr<Type> type;
namespace plsm {
namespace ast {
class TypeAlias : public Stmt {
const std::string alias;
const std::unique_ptr<Type> type;
public:
TypeAlias(LOC_ARG, const std::string &alias, std::unique_ptr<Type> &type)
: Stmt(location), alias(alias), type(std::move(type)) {}
};
}
public:
TypeAlias(LOC_ARG, const std::string &alias, std::unique_ptr<Type> &type)
: Stmt(location), alias(alias), type(std::move(type)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<TypeAlias> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,23 +1,29 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <string>
#include <memory>
#include <string>
#include <vector>
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<std::unique_ptr<FnArg>> attrs;
const std::vector<std::unique_ptr<FnDef>> members;
class TypeDef : public Stmt {
const std::string name;
const std::vector<std::unique_ptr<FnArg>> attrs;
const std::vector<std::unique_ptr<FnDef>> members;
public:
TypeDef(LOC_ARG, const std::string &name, std::vector<std::unique_ptr<FnArg>> &attrs, std::vector<std::unique_ptr<FnDef>> &members)
: Stmt(location), name(name), attrs(std::move(attrs)), members(std::move(members)) {}
};
}
public:
TypeDef(LOC_ARG, const std::string &name,
std::vector<std::unique_ptr<FnArg>> &attrs,
std::vector<std::unique_ptr<FnDef>> &members)
: Stmt(location), name(name), attrs(std::move(attrs)),
members(std::move(members)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<TypeDef> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,19 +1,24 @@
#pragma once
#include "AST/Base.h"
#include <string>
#include <memory>
#include <string>
namespace ast
{
class ValDecl : public Stmt
{
const std::string name;
const std::unique_ptr<Type> type;
const std::unique_ptr<Expr> value;
namespace plsm {
namespace ast {
class ValDecl : public Stmt {
const std::string name;
const std::unique_ptr<Type> type;
const std::unique_ptr<Expr> value;
public:
ValDecl(LOC_ARG, const std::string &name, std::unique_ptr<Type> &type, std::unique_ptr<Expr> &value)
: Stmt(location), name(name), type(std::move(type)), value(std::move(value)) {}
};
}
public:
ValDecl(LOC_ARG, const std::string &name, std::unique_ptr<Type> &type,
std::unique_ptr<Expr> &value)
: Stmt(location), name(name), type(std::move(type)),
value(std::move(value)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<ValDecl> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,18 +1,23 @@
#pragma once
#include "AST/Base.h"
#include <vector>
#include <memory>
#include <vector>
namespace ast
{
class ClosureType : public Type
{
const std::vector<std::unique_ptr<Type>> from;
const std::unique_ptr<Type> to;
namespace plsm {
namespace ast {
class ClosureType : public Type {
const std::vector<std::unique_ptr<Type>> from;
const std::unique_ptr<Type> to;
public:
ClosureType(LOC_ARG, std::vector<std::unique_ptr<Type>> &from, std::unique_ptr<Type> &to)
: Type(location), from(std::move(from)), to(std::move(to)) {}
};
}
public:
ClosureType(LOC_ARG, std::vector<std::unique_ptr<Type>> &from,
std::unique_ptr<Type> &to)
: Type(location), from(std::move(from)), to(std::move(to)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<ClosureType> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,19 +1,23 @@
#pragma once
#include "AST/Base.h"
#include <memory>
#include <string>
#include <vector>
#include <memory>
namespace ast
{
class GenericType : public Type
{
const std::string name;
const std::vector<std::unique_ptr<Type>> types;
namespace plsm {
namespace ast {
class GenericType : public Type {
const std::string name;
const std::vector<std::unique_ptr<Type>> types;
public:
GenericType(LOC_ARG, const std::string &name, std::vector<std::unique_ptr<Type>> &types)
: Type(location), name(name), types(std::move(types)) {}
};
}
public:
GenericType(LOC_ARG, const std::string &name,
std::vector<std::unique_ptr<Type>> &types)
: Type(location), name(name), types(std::move(types)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<GenericType> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -3,14 +3,18 @@
#include "AST/Base.h"
#include <string>
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) {}
};
}
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<NamedType> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -1,17 +1,21 @@
#pragma once
#include "AST/Def.h"
#include <vector>
#include <memory>
#include <vector>
namespace ast
{
class TupleType : public Type
{
const std::vector<std::unique_ptr<Type>> types;
namespace plsm {
namespace ast {
class TupleType : public Type {
const std::vector<std::unique_ptr<Type>> types;
public:
TupleType(LOC_ARG, std::vector<std::unique_ptr<Type>> &types)
: Type(location), types(std::move(types)) {}
};
}
public:
TupleType(LOC_ARG, std::vector<std::unique_ptr<Type>> &types)
: Type(location), types(std::move(types)) {}
virtual boost::json::value toJson() override;
static std::unique_ptr<TupleType> fromJson(boost::json::value json);
};
} // namespace ast
} // namespace plsm

View File

@ -4,15 +4,9 @@
#include <stdexcept>
#include "AST/Def.h"
#include "plsmLexer.h"
#include "plsmParser.h"
namespace plsm
{
std::unique_ptr<ast::Module> parse(const std::string &file, const std::string &input);
}
namespace adscript
{
std::unique_ptr<ast::Module> parse(const std::string &file, const std::string &input);
}

24
compiler/include/Utils.h Normal file
View File

@ -0,0 +1,24 @@
#include <boost/json.hpp>
#include <functional>
#include <vector>
namespace plsm {
namespace utils {
template <typename T> auto mapToJson(const std::vector<T> &vector) {
boost::json::array result(vector.size());
for (size_t i = 0; i < vector.size(); i++)
result[i] = vector[i]->toJson();
return result;
}
template <typename T, typename Mapper>
auto mapToJson(const std::vector<T> &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

View File

@ -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

View File

@ -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 .

113
compiler/src/AST/Base.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "AST/Def.h"
#include "AST/Expr/BinExpr.h"
#include "AST/Expr/Value.h"
#include <map>
#include <memory>
#include <stdexcept>
namespace plsm {
std::unique_ptr<ast::ASTNode> ast::ASTNode::fromJson(boost::json::value json) {
if (json.is_null())
return std::make_unique<NullValue>(ast::Location::json());
if (json.is_int64())
return std::make_unique<IntValue>(ast::Location::json(), json.as_int64());
if (json.is_double())
return std::make_unique<FloatValue>(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> ast::Expr::fromJson(boost::json::value json) {
auto node = ast::ASTNode::fromJson(json);
if (dynamic_cast<ast::Expr *>(node.get())) {
return std::unique_ptr<ast::Expr>((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> ast::Type::fromJson(boost::json::value json) {
auto node = ast::ASTNode::fromJson(json);
if (dynamic_cast<ast::Type *>(node.get())) {
return std::unique_ptr<ast::Type>((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> ast::Stmt::fromJson(boost::json::value json) {
auto node = ast::ASTNode::fromJson(json);
if (dynamic_cast<ast::Stmt *>(node.get())) {
return std::unique_ptr<ast::Stmt>((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

View File

@ -0,0 +1,37 @@
#include "AST/Expr/BinExpr.h"
#include "AST/Base.h"
#include "AST/Def.h"
#include <memory>
namespace plsm {
boost::json::value ast::BinExpr::toJson() {
return {
{"@type", "BinExpr"},
{"op", op},
{"left", left->toJson()},
{"right", right->toJson()},
};
}
std::unique_ptr<ast::BinExpr> ast::BinExpr::fromJson(boost::json::value json) {
auto op = getJsonValue<ast::BinExpr, std::string>(json, "op");
auto left = fromJsonProperty<ast::BinExpr, ast::Expr>(json, "left");
auto right = fromJsonProperty<ast::BinExpr, ast::Expr>(json, "right");
return std::make_unique<ast::BinExpr>(ast::Location::json(), left, op, right);
}
boost::json::value ast::PrefExpr::toJson() {
return {
{"@type", "PrefExpr"},
{"expr", expr->toJson()},
};
}
std::unique_ptr<ast::PrefExpr>
ast::PrefExpr::fromJson(boost::json::value json) {
auto expr = fromJsonProperty<ast::PrefExpr, ast::Expr>(json, "expr");
return std::make_unique<ast::PrefExpr>(ast::Location::json(), expr);
}
} // namespace plsm

View File

@ -0,0 +1,25 @@
#include "AST/Expr/Block.h"
#include "AST/Base.h"
#include "AST/Def.h"
#include "Utils.h"
#include <algorithm>
#include <memory>
namespace plsm {
boost::json::value ast::BlockExpr::toJson() {
return {
{"@type", "BlockExpr"},
{"stmts", utils::mapToJson(stmts)},
{"result", result->toJson()},
};
}
std::unique_ptr<ast::BlockExpr>
ast::BlockExpr::fromJson(boost::json::value json) {
auto stmts = fromJsonVector<ast::BlockExpr, ast::Stmt>(json, "stmts");
auto result = fromJsonProperty<ast::BlockExpr, ast::Expr>(json, "result");
return std::make_unique<ast::BlockExpr>(ast::Location::json(), stmts, result);
}
} // namespace plsm

View File

@ -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>
ast::CallExpr::fromJson(boost::json::value json) {
auto callee = fromJsonProperty<ast::CallExpr, ast::Expr>(json, "callee");
auto args = fromJsonVector<ast::CallExpr, ast::Expr>(json, "args");
return std::make_unique<ast::CallExpr>(ast::Location::json(), callee, args);
}
} // namespace plsm

View File

@ -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> ast::Closure::fromJson(boost::json::value json) {
auto args = fromJsonVector<ast::Closure, ast::FnArg>(json, "args");
auto body = fromJsonProperty<ast::Closure, ast::Expr>(json, "body");
return std::make_unique<ast::Closure>(ast::Location::json(), args, body);
}
} // namespace plsm

View File

@ -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>
ast::Identifier::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::Identifier, std::string>(json, "name");
return std::make_unique<ast::Identifier>(ast::Location::json(), name);
}
} // namespace plsm

View File

@ -0,0 +1,21 @@
#include "AST/Def.h"
#include <memory>
namespace plsm {
boost::json::value ast::PropExpr::toJson() {
return {
{"@type", "PropExpr"},
{"expr", expr->toJson()},
{"property", property},
};
}
std::unique_ptr<ast::PropExpr>
ast::PropExpr::fromJson(boost::json::value json) {
auto expr = fromJsonProperty<ast::PropExpr, ast::Expr>(json, "expr");
auto property = getJsonValue<ast::PropExpr, std::string>(json, "property");
return std::make_unique<ast::PropExpr>(ast::Location::json(), expr, property);
}
} // namespace plsm

View File

@ -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> ast::Tuple::fromJson(boost::json::value json) {
auto values = fromJsonVector<ast::Tuple, ast::Expr>(json, "values");
return std::make_unique<ast::Tuple>(ast::Location::json(), values);
}
} // namespace plsm

View File

@ -0,0 +1,22 @@
#include "AST/Def.h"
#include "AST/Expr/UnaryExpr.h"
#include <memory>
namespace plsm {
boost::json::value ast::UnaryExpr::toJson() {
return {
{"@type", "UnaryExpr"},
{"op", op},
{"expr", expr->toJson()},
};
}
std::unique_ptr<ast::UnaryExpr>
ast::UnaryExpr::fromJson(boost::json::value json) {
auto op = getJsonValue<ast::UnaryExpr, std::string>(json, "op");
auto expr = fromJsonProperty<ast::UnaryExpr, ast::Expr>(json, "expr");
return std::make_unique<ast::UnaryExpr>(ast::Location::json(), op, expr);
}
} // namespace plsm

View File

@ -0,0 +1,29 @@
#include "AST/Def.h"
#include <memory>
namespace plsm {
boost::json::value ast::NullValue::toJson() { return nullptr; }
std::unique_ptr<ast::NullValue>
ast::NullValue::fromJson(boost::json::value json) {
return std::make_unique<ast::NullValue>(ast::Location::json());
}
boost::json::value ast::IntValue::toJson() { return value; }
std::unique_ptr<ast::IntValue>
ast::IntValue::fromJson(boost::json::value json) {
return std::make_unique<ast::IntValue>(ast::Location::json(),
json.as_int64());
}
boost::json::value ast::FloatValue::toJson() { return value; }
std::unique_ptr<ast::FloatValue>
ast::FloatValue::fromJson(boost::json::value json) {
return std::make_unique<ast::FloatValue>(ast::Location::json(),
json.as_double());
}
} // namespace plsm

View File

@ -0,0 +1,19 @@
#include "AST/Def.h"
#include <memory>
namespace plsm {
boost::json::value ast::Import::toJson() {
return {
{"@type", "Import"},
{"moduleName", moduleName}
};
}
std::unique_ptr<ast::Import>
ast::Import::fromJson(boost::json::value json) {
auto moduleName = getJsonValue<ast::Import, std::string>(json, "moduleName");
return std::make_unique<ast::Import>(ast::Location::json(), moduleName);
}
} // namespace plsm

View File

@ -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> ast::Module::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::Module, std::string>(json, "name");
auto imports = fromJsonVector<ast::Module, ast::Import>(json, "imports");
auto stmts = fromJsonVector<ast::Module, ast::Stmt>(json, "stmts");
return std::make_unique<ast::Module>(ast::Location::json(), name, imports, stmts);
}
} // namespace plsm

View File

@ -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>
ast::ExprStmt::fromJson(boost::json::value json) {
auto expr = fromJsonProperty<ast::ExprStmt, ast::Expr>(json, "expr");
return std::make_unique<ast::ExprStmt>(ast::Location::json(), expr);
}
} // namespace plsm

View File

@ -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> ast::FnArg::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::FnArg, std::string>(json, "name");
auto type = fromJsonProperty<ast::FnArg, ast::Type>(json, "type");
return std::make_unique<ast::FnArg>(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> ast::FnDef::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::FnDef, std::string>(json, "name");
auto args = fromJsonVector<ast::FnDef, ast::FnArg>(json, "args");
auto returnType = fromJsonProperty<ast::FnDef, ast::Type>(json, "returnType");
auto body = fromJsonProperty<ast::FnDef, ast::Expr>(json, "body");
return std::make_unique<ast::FnDef>(ast::Location::json(), name, args,
returnType, body);
}
} // namespace plsm

View File

@ -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>
ast::TraitAlias::fromJson(boost::json::value json) {
auto alias = getJsonValue<ast::TraitAlias, std::string>(json, "alias");
auto aliased = getJsonValue<ast::TraitAlias, std::string>(json, "aliased");
return std::make_unique<ast::TraitAlias>(ast::Location::json(), alias,
aliased);
}
} // namespace plsm

View File

@ -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>
ast::TraitDef::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::TraitDef, std::string>(json, "name");
auto traits = fromJsonVector<ast::TraitDef, ast::FnDef>(json, "traits");
return std::make_unique<ast::TraitDef>(ast::Location::json(), name, traits);
}
} // namespace plsm

View File

@ -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>
ast::TypeAlias::fromJson(boost::json::value json) {
return nullptr;
}
} // namespace plsm

View File

@ -0,0 +1,25 @@
#include "AST/Def.h"
#include "AST/Stmt/FnDef.h"
#include "AST/Stmt/TypeDef.h"
#include "Utils.h"
#include <memory>
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> ast::TypeDef::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::TypeDef, std::string>(json, "name");
auto attrs = fromJsonVector<ast::TypeDef, ast::FnArg>(json, "attrs");
auto members = fromJsonVector<ast::TypeDef, ast::FnDef>(json, "members");
return std::make_unique<ast::TypeDef>(ast::Location::json(), name, attrs, members);
}
} // namespace plsm

View File

@ -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> ast::ValDecl::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::ValDecl, std::string>(json, "name");
auto type = fromJsonProperty<ast::ValDecl, ast::Type>(json, "type");
auto value = fromJsonProperty<ast::ValDecl, ast::Expr>(json, "value");
return std::make_unique<ast::ValDecl>(ast::Location::json(), name, type, value);
}
} // namespace plsm

View File

@ -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>
ast::ClosureType::fromJson(boost::json::value json) {
auto from = fromJsonVector<ast::ClosureType, ast::Type>(json, "from");
auto to = fromJsonProperty<ast::ClosureType, ast::Type>(json, "to");
return std::make_unique<ast::ClosureType>(ast::Location::json(), from, to);
}
} // namespace plsm

View File

@ -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>
ast::GenericType::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::GenericType, std::string>(json, "name");
auto types = fromJsonVector<ast::GenericType, ast::Type>(json, "types");
return std::make_unique<ast::GenericType>(ast::Location::json(), name, types);
}
} // namespace plsm

View File

@ -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>
ast::NamedType::fromJson(boost::json::value json) {
auto name = getJsonValue<ast::NamedType, std::string>(json, "name");
return std::make_unique<ast::NamedType>(ast::Location::json(), name);
}
} // namespace plsm

View File

@ -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>
ast::TupleType::fromJson(boost::json::value json) {
auto types = fromJsonVector<ast::TupleType, ast::Type>(json, "types");
return std::make_unique<ast::TupleType>(ast::Location::json(), types);
}
} // namespace plsm

View File

@ -1,11 +1,16 @@
#include "Parser.h"
#include "plsmBaseVisitor.h"
#include "AST/Def.h"
#include <any>
#include <sstream>
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<size_t, size_t>(
ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine()),
std::pair<size_t, size_t>(
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<size_t, size_t>(ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine()),
std::pair<size_t, size_t>(ctx->getStop()->getLine(),
ctx->getStop()->getCharPositionInLine()));
}
template <typename T> inline T visitT(antlr4::tree::ParseTree *ctx) {
return std::any_cast<T>(visit(ctx));
}
template <typename T>
inline std::unique_ptr<T> visitU(antlr4::tree::ParseTree *ctx) {
return std::unique_ptr<T>(visitT<T *>(ctx));
}
template <typename T>
inline std::vector<std::unique_ptr<T>> visitVU(antlr4::tree::ParseTree *ctx) {
std::vector<std::unique_ptr<T>> res;
for (auto &el : visitT<std::vector<T *>>(ctx))
res.push_back(std::unique_ptr<T>(el));
return res;
}
virtual std::any visitModule(plsmParser::ModuleContext *ctx) override {
auto name = ctx->identifier()->getText();
std::vector<std::unique_ptr<ast::Import>> imports;
for (auto &import : ctx->moduleImport())
imports.push_back(visitU<ast::Import>(import));
std::vector<std::unique_ptr<ast::Stmt>> stmts;
for (auto &stmt : ctx->moduleStmt())
stmts.push_back(visitU<ast::Stmt>(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<std::string>(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<ast::ValDecl *>(ctx->let());
if (ctx->fnDecl())
stmt = (ast::Stmt *)visitT<ast::FnDef *>(ctx->fnDecl());
if (ctx->fnDef())
stmt = (ast::Stmt *)visitT<ast::FnDef *>(ctx->fnDef());
if (ctx->traitDef())
stmt = (ast::Stmt *)visitT<ast::Stmt *>(ctx->traitDef());
if (ctx->typeDef())
stmt = (ast::Stmt *)visitT<ast::Stmt *>(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 <typename T>
inline T visitT(antlr4::tree::ParseTree *ctx)
{
return std::any_cast<T>(visit(ctx));
std::vector<std::unique_ptr<ast::FnDef>> fns;
for (auto &decl : ctx->fnDecl())
fns.push_back(visitU<ast::FnDef>(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<ast::Type>(ctx->type());
return std::any((ast::Stmt *)new ast::TypeAlias(loc(ctx), name, gen));
}
template <typename T>
inline std::unique_ptr<T> visitU(antlr4::tree::ParseTree *ctx)
{
return std::unique_ptr<T>(visitT<T *>(ctx));
std::vector<std::unique_ptr<ast::FnArg>> attrs;
if (ctx->fnDefArgs())
attrs = visitVU<ast::FnArg>(ctx->fnDefArgs());
std::vector<std::unique_ptr<ast::FnDef>> members;
for (auto &def : ctx->fnDef())
members.push_back(visitU<ast::FnDef>(def));
for (auto &decl : ctx->fnDecl())
members.push_back(visitU<ast::FnDef>(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<std::unique_ptr<ast::FnArg>> args;
if (ctx->fnDefArgs())
args = std::move(visitVU<ast::FnArg>(ctx->fnDefArgs()));
auto returnType = visitU<ast::Type>(ctx->type());
auto body = visitU<ast::Expr>(ctx->expr());
return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body));
}
virtual std::any visitFnDefArgs(plsmParser::FnDefArgsContext *ctx) override {
std::vector<ast::FnArg *> args;
for (size_t i = 0; i < ctx->children.size(); i += 3) {
auto name = ctx->children[i]->getText();
auto type = visitU<ast::Type>(ctx->children[i + 1]);
args.push_back(new ast::FnArg(loc(ctx), name, type));
}
template <typename T>
inline std::vector<std::unique_ptr<T>> visitVU(antlr4::tree::ParseTree *ctx)
{
std::vector<std::unique_ptr<T>> res;
for (auto &el : visitT<std::vector<T *>>(ctx))
res.push_back(std::unique_ptr<T>(el));
return res;
return std::any(args);
}
virtual std::any visitFnDecl(plsmParser::FnDeclContext *ctx) override {
auto name = ctx->identifier()->getText();
std::vector<std::unique_ptr<ast::FnArg>> args;
if (ctx->fnDeclArgs())
args = visitVU<ast::FnArg>(ctx->fnDeclArgs());
auto returnType = visitU<ast::Type>(ctx->type());
auto body = std::unique_ptr<ast::Expr>(nullptr);
return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body));
}
virtual std::any
visitFnDeclArgs(plsmParser::FnDeclArgsContext *ctx) override {
std::vector<ast::FnArg *> args;
for (size_t i = 0; i < ctx->children.size(); i++) {
std::string name;
if (dynamic_cast<plsmParser::IdentifierContext *>(ctx->children[i]))
name = ctx->children[i++]->getText();
auto type = visitU<ast::Type>(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<std::unique_ptr<ast::Import>> imports;
for (auto &import : ctx->moduleImport())
imports.push_back(visitU<ast::Import>(import));
virtual std::any visitLet(plsmParser::LetContext *ctx) override {
auto name = ctx->identifier()->getText();
std::vector<std::unique_ptr<ast::Stmt>> stmts;
for (auto &stmt : ctx->moduleStmt())
stmts.push_back(visitU<ast::Stmt>(stmt));
std::unique_ptr<ast::Type> type(nullptr);
if (ctx->type())
type = visitU<ast::Type>(ctx->type());
return std::any(new ast::Module(loc(ctx), name, imports, stmts));
}
auto expr = visitU<ast::Expr>(ctx->expr());
virtual std::any visitModuleImport(plsmParser::ModuleImportContext *ctx) override
{
return std::any(new ast::Import(loc(ctx), visitT<std::string>(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<ast::Expr>(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<ast::ValDecl *>(ctx->let());
if (ctx->fnDecl())
stmt = (ast::Stmt *)visitT<ast::FnDef *>(ctx->fnDecl());
if (ctx->fnDef())
stmt = (ast::Stmt *)visitT<ast::FnDef *>(ctx->fnDef());
if (ctx->traitDef())
stmt = (ast::Stmt *)visitT<ast::Stmt *>(ctx->traitDef());
if (ctx->typeDef())
stmt = (ast::Stmt *)visitT<ast::Stmt *>(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<std::unique_ptr<ast::FnDef>> fns;
for (auto &decl : ctx->fnDecl())
fns.push_back(visitU<ast::FnDef>(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<ast::Type>(ctx->type());
return std::any((ast::Stmt *)new ast::TypeAlias(loc(ctx), name, gen));
return visit(ctx->type());
if (ctx->tupleTypeList()) {
auto types = visitVU<ast::Type>(ctx->tupleTypeList());
return std::any((ast::Type *)new ast::TupleType(loc(ctx), types));
}
std::vector<std::unique_ptr<ast::FnArg>> attrs;
if (ctx->fnDefArgs())
attrs = visitVU<ast::FnArg>(ctx->fnDefArgs());
std::vector<std::unique_ptr<ast::FnDef>> members;
for (auto &def : ctx->fnDef())
members.push_back(visitU<ast::FnDef>(def));
for (auto &decl : ctx->fnDecl())
members.push_back(visitU<ast::FnDef>(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<std::unique_ptr<ast::FnArg>> args;
if (ctx->fnDefArgs())
args = std::move(visitVU<ast::FnArg>(ctx->fnDefArgs()));
if (ctx->children[0]->getText() == "[") {
std::vector<std::unique_ptr<ast::Type>> args;
if (ctx->typeList())
args = visitVU<ast::Type>(ctx->typeList());
auto returnType = visitU<ast::Type>(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<ast::Type>(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<ast::Type *> types;
for (auto &type : ctx->type())
types.push_back(visitT<ast::Type *>(type));
return std::any(types);
}
virtual std::any visitTypeList(plsmParser::TypeListContext *ctx) override {
std::vector<ast::Type *> types;
for (auto &type : ctx->type())
types.push_back(visitT<ast::Type *>(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<std::unique_ptr<ast::FnArg>> args;
if (ctx->fnDefArgs())
args = visitVU<ast::FnArg>(ctx->fnDefArgs());
auto body = visitU<ast::Expr>(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<ast::FnArg *> args;
// block
if (ctx->children[0]->getText() == "{") {
std::vector<std::unique_ptr<ast::Stmt>> stmts;
for (auto &stmt : ctx->blockStmt())
stmts.push_back(visitU<ast::Stmt>(stmt));
for (size_t i = 0; i < ctx->children.size(); i += 3)
{
auto name = ctx->children[i]->getText();
auto type = visitU<ast::Type>(ctx->children[i + 1]);
args.push_back(new ast::FnArg(loc(ctx), name, type));
}
auto result = visitU<ast::Expr>(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<std::unique_ptr<ast::FnArg>> args;
if (ctx->fnDeclArgs())
args = visitVU<ast::FnArg>(ctx->fnDeclArgs());
auto returnType = visitU<ast::Type>(ctx->type());
auto body = std::unique_ptr<ast::Expr>(nullptr);
return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body));
}
virtual std::any visitFnDeclArgs(plsmParser::FnDeclArgsContext *ctx) override
{
std::vector<ast::FnArg *> args;
for (size_t i = 0; i < ctx->children.size(); i++)
{
std::string name;
if (dynamic_cast<plsmParser::IdentifierContext *>(ctx->children[i]))
name = ctx->children[i++]->getText();
auto type = visitU<ast::Type>(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<ast::Type> type(nullptr);
if (ctx->type())
type = visitU<ast::Type>(ctx->type());
auto expr = visitU<ast::Expr>(ctx->expr());
return std::any(new ast::ValDecl(loc(ctx), name, type, expr));
}
virtual std::any visitExprStmt(plsmParser::ExprStmtContext *ctx) override
{
auto expr = visitU<ast::Expr>(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<ast::Type>(ctx->tupleTypeList());
return std::any((ast::Type *)new ast::TupleType(loc(ctx), types));
}
}
if (ctx->children[0]->getText() == "[")
{
std::vector<std::unique_ptr<ast::Type>> args;
if (ctx->typeList())
args = visitVU<ast::Type>(ctx->typeList());
auto returnType = visitU<ast::Type>(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<ast::Type>(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<ast::Type *> types;
for (auto &type : ctx->type())
types.push_back(visitT<ast::Type *>(type));
return std::any(types);
}
virtual std::any visitTypeList(plsmParser::TypeListContext *ctx) override
{
std::vector<ast::Type *> types;
for (auto &type : ctx->type())
types.push_back(visitT<ast::Type *>(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<std::string> args;
if (ctx->identifierList())
args = visitT<std::vector<std::string>>(ctx->identifierList());
auto body = visitU<ast::Expr>(ctx->expr());
return std::any((ast::Expr *)new ast::Closure(loc(ctx), args, body));
}
// block
if (ctx->children[0]->getText() == "{")
{
std::vector<std::unique_ptr<ast::Stmt>> stmts;
for (auto &stmt : ctx->blockStmt())
stmts.push_back(visitU<ast::Stmt>(stmt));
auto result = visitU<ast::Expr>(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<ast::Expr>(ctx->expr2());
auto op = ctx->operator_()->getText();
auto right = visitU<ast::Expr>(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<ast::Expr>(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<ast::Expr>(ctx->expr());
return std::any((ast::Expr *)new ast::PrefExpr(loc(ctx), expr));
}
if (ctx->expr0())
{
auto expr = visitU<ast::Expr>(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<std::unique_ptr<ast::Expr>> args;
if (ctx->exprList())
args = visitVU<ast::Expr>(ctx->exprList());
return std::any((ast::Expr *)new ast::CallExpr(loc(ctx), expr, args));
}
// tuple
if (ctx->tupleExprList())
{
auto values = visitVU<ast::Expr>(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<ast::ValDecl *>(ctx->let());
if (ctx->exprStmt())
stmt = (ast::Stmt *)visitT<ast::ExprStmt *>(ctx->exprStmt());
if (ctx->fnDef())
stmt = (ast::Stmt *)visitT<ast::FnDef *>(ctx->fnDef());
return std::any(stmt);
}
virtual std::any visitTupleExprList(plsmParser::TupleExprListContext *ctx) override
{
std::vector<ast::Expr *> exprs;
for (auto &expr : ctx->expr())
exprs.push_back(visitT<ast::Expr *>(expr));
return std::any(exprs);
}
virtual std::any visitExprList(plsmParser::ExprListContext *ctx) override
{
std::vector<ast::Expr *> exprs;
for (auto &expr : ctx->expr())
exprs.push_back(visitT<ast::Expr *>(expr));
return std::any(exprs);
}
virtual std::any visitIdentifierList(plsmParser::IdentifierListContext *ctx) override
{
std::vector<std::string> identifiers;
for (auto &identifier : ctx->identifier())
identifiers.push_back(visitT<std::string>(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<ast::Module> 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<ast::Module *>(Visitor(file).visitModule(tree));
return std::unique_ptr<ast::Module>(module);
throw std::logic_error("expr3 not implemented");
}
virtual std::any visitExpr2(plsmParser::Expr2Context *ctx) override {
if (ctx->expr2()) {
auto left = visitU<ast::Expr>(ctx->expr2());
auto op = ctx->operator_()->getText();
auto right = visitU<ast::Expr>(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<ast::Expr>(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<ast::Expr>(ctx->expr());
return std::any((ast::Expr *)new ast::PrefExpr(loc(ctx), expr));
}
if (ctx->expr0()) {
auto expr = visitU<ast::Expr>(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<std::unique_ptr<ast::Expr>> args;
if (ctx->exprList())
args = visitVU<ast::Expr>(ctx->exprList());
return std::any((ast::Expr *)new ast::CallExpr(loc(ctx), expr, args));
}
// tuple
if (ctx->tupleExprList()) {
auto values = visitVU<ast::Expr>(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<ast::ValDecl *>(ctx->let());
if (ctx->exprStmt())
stmt = (ast::Stmt *)visitT<ast::ExprStmt *>(ctx->exprStmt());
if (ctx->fnDef())
stmt = (ast::Stmt *)visitT<ast::FnDef *>(ctx->fnDef());
return std::any(stmt);
}
virtual std::any
visitTupleExprList(plsmParser::TupleExprListContext *ctx) override {
std::vector<ast::Expr *> exprs;
for (auto &expr : ctx->expr())
exprs.push_back(visitT<ast::Expr *>(expr));
return std::any(exprs);
}
virtual std::any visitExprList(plsmParser::ExprListContext *ctx) override {
std::vector<ast::Expr *> exprs;
for (auto &expr : ctx->expr())
exprs.push_back(visitT<ast::Expr *>(expr));
return std::any(exprs);
}
virtual std::any
visitIdentifierList(plsmParser::IdentifierListContext *ctx) override {
std::vector<std::string> identifiers;
for (auto &identifier : ctx->identifier())
identifiers.push_back(visitT<std::string>(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<ast::Module> 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<ast::Module *>(Visitor(file).visitModule(tree));
return std::unique_ptr<ast::Module>(module);
}
std::unique_ptr<ast::Module>
adscript::parse(const std::string &file, const std::string &input)
{
throw std::logic_error("adscript::parse not implemented");
}
} // namespace plsm

View File

@ -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)
{

BIN
compiler/thirdparty/antlr-4.13.1.zip vendored Normal file

Binary file not shown.