updated antlr4 version, further progress (TypeAnalysis)
This commit is contained in:
parent
e35ceeacf9
commit
c23fc2ee86
@ -30,7 +30,7 @@ add_custom_command(PRE_BUILD
|
|||||||
OUTPUT ${ANTLR_INC}
|
OUTPUT ${ANTLR_INC}
|
||||||
COMMENT "Generating plsm_parser"
|
COMMENT "Generating plsm_parser"
|
||||||
COMMAND java -jar
|
COMMAND java -jar
|
||||||
${CMAKE_SOURCE_DIR}/thirdparty/antlr-4.13.1-complete.jar
|
${CMAKE_SOURCE_DIR}/thirdparty/antlr4-4.13.2-complete.jar
|
||||||
${CMAKE_SOURCE_DIR}/plsm.g4
|
${CMAKE_SOURCE_DIR}/plsm.g4
|
||||||
-o ${GEN_DIR} -Dlanguage=Cpp -no-listener -visitor
|
-o ${GEN_DIR} -Dlanguage=Cpp -no-listener -visitor
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${GEN_DIR}/*.h ${INC_DIR}
|
COMMAND ${CMAKE_COMMAND} -E copy ${GEN_DIR}/*.h ${INC_DIR}
|
||||||
|
@ -9,7 +9,7 @@ include(ExternalProject)
|
|||||||
set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime)
|
set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime)
|
||||||
set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src)
|
set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src)
|
||||||
# set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git)
|
# set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git)
|
||||||
set(ANTLR4_ZIP_REPOSITORY ${PROJECT_SOURCE_DIR}/thirdparty/antlr-4.13.1.zip)
|
set(ANTLR4_ZIP_REPOSITORY ${PROJECT_SOURCE_DIR}/thirdparty/antlr4-4.13.2.zip)
|
||||||
if(NOT DEFINED ANTLR4_TAG)
|
if(NOT DEFINED ANTLR4_TAG)
|
||||||
# Set to branch name to keep library updated at the cost of needing to rebuild after 'clean'
|
# 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 to commit hash to keep the build stable and does not need to rebuild after 'clean'
|
||||||
@ -47,7 +47,7 @@ else()
|
|||||||
set(ANTLR4_SHARED_LIBRARIES
|
set(ANTLR4_SHARED_LIBRARIES
|
||||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a)
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a)
|
||||||
set(ANTLR4_RUNTIME_LIBRARIES
|
set(ANTLR4_RUNTIME_LIBRARIES
|
||||||
${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.13.1.dll)
|
${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.13.2.dll)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
set(ANTLR4_RUNTIME_LIBRARIES
|
set(ANTLR4_RUNTIME_LIBRARIES
|
||||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib)
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "Module/Module.h"
|
#include "Module/Module.h"
|
||||||
|
|
||||||
#include "Stmt/AssignStmt.h"
|
#include "Stmt/AssignStmt.h"
|
||||||
|
#include "Stmt/Block.h"
|
||||||
#include "Stmt/ExprStmt.h"
|
#include "Stmt/ExprStmt.h"
|
||||||
#include "Stmt/FnDecl.h"
|
#include "Stmt/FnDecl.h"
|
||||||
#include "Stmt/IfStmt.h"
|
#include "Stmt/IfStmt.h"
|
||||||
@ -24,4 +25,4 @@
|
|||||||
#include "Type/FunctionType.h"
|
#include "Type/FunctionType.h"
|
||||||
#include "Type/PrimitiveType.h"
|
#include "Type/PrimitiveType.h"
|
||||||
|
|
||||||
#include "TypeName/PrimitiveTypeName.h"
|
#include "TypeName/NamedTypeName.h"
|
||||||
|
@ -3,15 +3,17 @@
|
|||||||
#include <any>
|
#include <any>
|
||||||
#include <boost/json/serialize.hpp>
|
#include <boost/json/serialize.hpp>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
|
|
||||||
|
#include "Terminal.h"
|
||||||
|
|
||||||
#define LOC_ARG const SourceRange &sourceRange
|
#define LOC_ARG const SourceRange &sourceRange
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
@ -30,6 +32,7 @@ class Import;
|
|||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
class AssignStmt;
|
class AssignStmt;
|
||||||
|
class Block;
|
||||||
class ExprStmt;
|
class ExprStmt;
|
||||||
class FnParam;
|
class FnParam;
|
||||||
class FnDecl;
|
class FnDecl;
|
||||||
@ -38,7 +41,7 @@ class RetStmt;
|
|||||||
class VarDecl;
|
class VarDecl;
|
||||||
class WhileStmt;
|
class WhileStmt;
|
||||||
|
|
||||||
class PrimitiveTypeName;
|
class NamedTypeName;
|
||||||
|
|
||||||
class ASTVisitor {
|
class ASTVisitor {
|
||||||
public:
|
public:
|
||||||
@ -57,6 +60,7 @@ public:
|
|||||||
virtual std::any visit(Module &module, std::any param) = 0;
|
virtual std::any visit(Module &module, std::any param) = 0;
|
||||||
|
|
||||||
virtual std::any visit(AssignStmt &assignStmt, std::any param) = 0;
|
virtual std::any visit(AssignStmt &assignStmt, std::any param) = 0;
|
||||||
|
virtual std::any visit(Block &block, std::any param) = 0;
|
||||||
virtual std::any visit(ExprStmt &exprStmt, std::any param) = 0;
|
virtual std::any visit(ExprStmt &exprStmt, std::any param) = 0;
|
||||||
virtual std::any visit(FnParam &fnParam, std::any param) = 0;
|
virtual std::any visit(FnParam &fnParam, std::any param) = 0;
|
||||||
virtual std::any visit(FnDecl &fnDecl, std::any param) = 0;
|
virtual std::any visit(FnDecl &fnDecl, std::any param) = 0;
|
||||||
@ -65,8 +69,7 @@ public:
|
|||||||
virtual std::any visit(VarDecl &varDecl, std::any param) = 0;
|
virtual std::any visit(VarDecl &varDecl, std::any param) = 0;
|
||||||
virtual std::any visit(WhileStmt &whileStmt, std::any param) = 0;
|
virtual std::any visit(WhileStmt &whileStmt, std::any param) = 0;
|
||||||
|
|
||||||
virtual std::any visit(PrimitiveTypeName &primitiveTypeName,
|
virtual std::any visit(NamedTypeName &namedTypeName, std::any param) = 0;
|
||||||
std::any param) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
@ -79,7 +82,7 @@ class Jsonable {
|
|||||||
public:
|
public:
|
||||||
virtual ~Jsonable() = default;
|
virtual ~Jsonable() = default;
|
||||||
|
|
||||||
virtual boost::json::value toJson() = 0;
|
virtual boost::json::value toJson() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <class CurrNode>
|
template <class CurrNode>
|
||||||
@ -114,7 +117,8 @@ protected:
|
|||||||
template <class CurrNode, class SubNode>
|
template <class CurrNode, class SubNode>
|
||||||
static inline auto fromJsonProperty(boost::json::value json,
|
static inline auto fromJsonProperty(boost::json::value json,
|
||||||
std::string property) {
|
std::string property) {
|
||||||
return SubNode::fromJson(getJsonProperty<CurrNode>(json, property));
|
return std::unique_ptr<SubNode>(
|
||||||
|
SubNode::fromJson(getJsonProperty<CurrNode>(json, property)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class CurrNode, class SubNode>
|
template <class CurrNode, class SubNode>
|
||||||
@ -122,9 +126,9 @@ protected:
|
|||||||
std::string property) {
|
std::string property) {
|
||||||
auto arr = getJsonProperty<CurrNode>(json, property).as_array();
|
auto arr = getJsonProperty<CurrNode>(json, property).as_array();
|
||||||
|
|
||||||
std::vector<SubNode *> result;
|
std::vector<std::unique_ptr<SubNode>> result;
|
||||||
for (auto &el : arr) {
|
for (auto &el : arr) {
|
||||||
result.push_back(SubNode::fromJson(el));
|
result.push_back(std::unique_ptr<SubNode>(SubNode::fromJson(el)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -133,7 +137,7 @@ protected:
|
|||||||
|
|
||||||
class SourceRange {
|
class SourceRange {
|
||||||
public:
|
public:
|
||||||
SourceRange(const std::string &file, const std::string &text,
|
SourceRange(const std::string &file, std::string text,
|
||||||
std::pair<size_t, size_t> start, std::pair<size_t, size_t> end)
|
std::pair<size_t, size_t> start, std::pair<size_t, size_t> end)
|
||||||
: file(file), text(text), start(start), end(end) {}
|
: file(file), text(text), start(start), end(end) {}
|
||||||
|
|
||||||
@ -141,27 +145,34 @@ public:
|
|||||||
const std::pair<size_t, size_t> start, end;
|
const std::pair<size_t, size_t> start, end;
|
||||||
|
|
||||||
static SourceRange unknown() {
|
static SourceRange unknown() {
|
||||||
return SourceRange("<?>", "<?>", {-1, -1}, {-1, -1});
|
return SourceRange("<?>", "<?>", {0, 0}, {0, 0});
|
||||||
};
|
};
|
||||||
|
|
||||||
static SourceRange json() {
|
static SourceRange json() {
|
||||||
return SourceRange("<json>", "<?>", {-1, -1}, {-1, -1});
|
return SourceRange("<json>", "<json>", {0, 0}, {0, 0});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TypeName;
|
||||||
|
|
||||||
class Type : public Jsonable {
|
class Type : public Jsonable {
|
||||||
public:
|
public:
|
||||||
Type() : Jsonable() {}
|
Type() : Jsonable() {}
|
||||||
virtual ~Type() = default;
|
virtual ~Type() = default;
|
||||||
|
|
||||||
|
virtual TypeName *toTypeName() = 0;
|
||||||
|
|
||||||
|
virtual bool operator==(const Type &other) = 0;
|
||||||
|
virtual bool operator!=(const Type &other) { return !(*this == other); }
|
||||||
|
|
||||||
static Type *fromJson(boost::json::value json);
|
static Type *fromJson(boost::json::value json);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Symbol {
|
class Symbol {
|
||||||
|
public:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
std::shared_ptr<Type> type;
|
std::shared_ptr<Type> type;
|
||||||
|
|
||||||
public:
|
|
||||||
Symbol(const std::string &name) : name(name) {}
|
Symbol(const std::string &name) : name(name) {}
|
||||||
Symbol(const std::string &name, Type *type) : name(name), type(type) {}
|
Symbol(const std::string &name, Type *type) : name(name), type(type) {}
|
||||||
};
|
};
|
||||||
@ -173,29 +184,40 @@ public:
|
|||||||
|
|
||||||
const SourceRange sourceRange;
|
const SourceRange sourceRange;
|
||||||
|
|
||||||
virtual std::string toJsonString() {
|
virtual std::string toJsonString() const {
|
||||||
return boost::json::serialize(toJson(), {});
|
return boost::json::serialize(toJson(), {});
|
||||||
}
|
}
|
||||||
|
|
||||||
static ASTNode *fromJson(boost::json::value json);
|
static ASTNode *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual bool isExpr() { return false; }
|
virtual bool isExpr() const { return false; }
|
||||||
virtual bool isStmt() { return false; }
|
virtual bool isStmt() const { return false; }
|
||||||
virtual bool isTypeName() { return false; }
|
virtual bool isTypeName() const { return false; }
|
||||||
|
|
||||||
|
virtual std::string error(const std::string &message) const {
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << "In file " << sourceRange.file << ":" << sourceRange.start.first
|
||||||
|
<< ":" << sourceRange.start.second + 1 << "\n"
|
||||||
|
<< terminal::cyan << sourceRange.text << terminal::reset << "\n"
|
||||||
|
<< terminal::red << message << terminal::reset;
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) = 0;
|
virtual std::any accept(ASTVisitor *visitor, std::any param) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Expr : public ASTNode {
|
class Expr : public ASTNode {
|
||||||
|
public:
|
||||||
std::shared_ptr<Type> type;
|
std::shared_ptr<Type> type;
|
||||||
|
|
||||||
public:
|
|
||||||
Expr(LOC_ARG) : ASTNode(sourceRange) {}
|
Expr(LOC_ARG) : ASTNode(sourceRange) {}
|
||||||
virtual ~Expr() = default;
|
virtual ~Expr() = default;
|
||||||
|
|
||||||
static Expr *fromJson(boost::json::value json);
|
static Expr *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual bool isExpr() override { return true; }
|
virtual bool isExpr() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Stmt : public ASTNode {
|
class Stmt : public ASTNode {
|
||||||
@ -205,17 +227,19 @@ public:
|
|||||||
|
|
||||||
static Stmt *fromJson(boost::json::value json);
|
static Stmt *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual bool isStmt() override { return true; }
|
virtual bool isStmt() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class TypeName : public ASTNode {
|
class TypeName : public ASTNode {
|
||||||
public:
|
public:
|
||||||
|
std::shared_ptr<Type> type;
|
||||||
|
|
||||||
TypeName(LOC_ARG) : ASTNode(sourceRange) {}
|
TypeName(LOC_ARG) : ASTNode(sourceRange) {}
|
||||||
virtual ~TypeName() = default;
|
virtual ~TypeName() = default;
|
||||||
|
|
||||||
static TypeName *fromJson(boost::json::value json);
|
static TypeName *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual bool isTypeName() override { return true; }
|
virtual bool isTypeName() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -10,15 +10,19 @@ public:
|
|||||||
BaseASTVisitor() : ASTVisitor() {};
|
BaseASTVisitor() : ASTVisitor() {};
|
||||||
|
|
||||||
virtual std::any visit(BinExpr &binExpr, std::any param) override {
|
virtual std::any visit(BinExpr &binExpr, std::any param) override {
|
||||||
|
if (binExpr.lhs.get())
|
||||||
binExpr.lhs->accept(this, param);
|
binExpr.lhs->accept(this, param);
|
||||||
|
if (binExpr.rhs.get())
|
||||||
binExpr.rhs->accept(this, param);
|
binExpr.rhs->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(CallExpr &callExpr, std::any param) override {
|
virtual std::any visit(CallExpr &callExpr, std::any param) override {
|
||||||
|
if (callExpr.callee.get())
|
||||||
callExpr.callee->accept(this, param);
|
callExpr.callee->accept(this, param);
|
||||||
|
|
||||||
for (auto &arg : callExpr.args) {
|
for (auto &arg : callExpr.args) {
|
||||||
|
if (arg.get())
|
||||||
arg->accept(this, param);
|
arg->accept(this, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +30,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(CastExpr &castExpr, std::any param) override {
|
virtual std::any visit(CastExpr &castExpr, std::any param) override {
|
||||||
|
if (castExpr.value.get())
|
||||||
castExpr.value->accept(this, param);
|
castExpr.value->accept(this, param);
|
||||||
|
if (castExpr.typeName.get())
|
||||||
castExpr.typeName->accept(this, param);
|
castExpr.typeName->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
@ -36,18 +42,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(LambdaExpr &lambdaExpr, std::any param) override {
|
virtual std::any visit(LambdaExpr &lambdaExpr, std::any param) override {
|
||||||
for (auto ¶m : lambdaExpr.params) {
|
if (lambdaExpr.returnTypeName.get())
|
||||||
param->accept(this, param);
|
lambdaExpr.returnTypeName->accept(this, param);
|
||||||
|
|
||||||
|
for (auto &p : lambdaExpr.params) {
|
||||||
|
if (p.get())
|
||||||
|
p->accept(this, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &body : lambdaExpr.body) {
|
if (lambdaExpr.body.get())
|
||||||
body->accept(this, param);
|
lambdaExpr.body->accept(this, param);
|
||||||
}
|
|
||||||
|
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(UnExpr &unExpr, std::any param) override {
|
virtual std::any visit(UnExpr &unExpr, std::any param) override {
|
||||||
|
if (unExpr.expr.get())
|
||||||
unExpr.expr->accept(this, param);
|
unExpr.expr->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
@ -70,6 +80,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &stmt : module.stmts) {
|
for (auto &stmt : module.stmts) {
|
||||||
|
if (stmt.get())
|
||||||
stmt->accept(this, param);
|
stmt->accept(this, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,68 +88,82 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(AssignStmt &assignStmt, std::any param) override {
|
virtual std::any visit(AssignStmt &assignStmt, std::any param) override {
|
||||||
|
if (assignStmt.lval.get())
|
||||||
assignStmt.lval->accept(this, param);
|
assignStmt.lval->accept(this, param);
|
||||||
|
if (assignStmt.rval.get())
|
||||||
assignStmt.rval->accept(this, param);
|
assignStmt.rval->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(Block &block, std::any param) override {
|
||||||
|
for (auto &stmt : block.stmts) {
|
||||||
|
if (stmt.get())
|
||||||
|
stmt->accept(this, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::any visit(ExprStmt &exprStmt, std::any param) override {
|
virtual std::any visit(ExprStmt &exprStmt, std::any param) override {
|
||||||
|
if (exprStmt.expr.get())
|
||||||
exprStmt.expr->accept(this, param);
|
exprStmt.expr->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(FnParam &fnParam, std::any param) override {
|
virtual std::any visit(FnParam &fnParam, std::any param) override {
|
||||||
|
if (fnParam.typeName.get())
|
||||||
fnParam.typeName->accept(this, param);
|
fnParam.typeName->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(FnDecl &fnDecl, std::any param) override {
|
virtual std::any visit(FnDecl &fnDecl, std::any param) override {
|
||||||
for (auto ¶m : fnDecl.params) {
|
if (fnDecl.returnTypeName.get())
|
||||||
param->accept(this, param);
|
fnDecl.returnTypeName->accept(this, param);
|
||||||
|
|
||||||
|
for (auto &p : fnDecl.params) {
|
||||||
|
if (p.get())
|
||||||
|
p->accept(this, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &body : fnDecl.body) {
|
if (fnDecl.body.get())
|
||||||
body->accept(this, param);
|
fnDecl.body->accept(this, param);
|
||||||
}
|
|
||||||
|
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(IfStmt &ifStmt, std::any param) override {
|
virtual std::any visit(IfStmt &ifStmt, std::any param) override {
|
||||||
|
if (ifStmt.condition.get())
|
||||||
ifStmt.condition->accept(this, param);
|
ifStmt.condition->accept(this, param);
|
||||||
|
if (ifStmt.ifBody.get())
|
||||||
for (auto &ifBody : ifStmt.ifBody) {
|
ifStmt.ifBody->accept(this, param);
|
||||||
ifBody->accept(this, param);
|
if (ifStmt.elseBody.get())
|
||||||
}
|
ifStmt.elseBody->accept(this, param);
|
||||||
|
|
||||||
for (auto &elseBody : ifStmt.elseBody) {
|
|
||||||
elseBody->accept(this, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(RetStmt &retStmt, std::any param) override {
|
virtual std::any visit(RetStmt &retStmt, std::any param) override {
|
||||||
|
if (retStmt.value.get())
|
||||||
retStmt.value->accept(this, param);
|
retStmt.value->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(VarDecl &varDecl, std::any param) override {
|
virtual std::any visit(VarDecl &varDecl, std::any param) override {
|
||||||
|
if (varDecl.typeName.get())
|
||||||
varDecl.typeName->accept(this, param);
|
varDecl.typeName->accept(this, param);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(WhileStmt &whileStmt, std::any param) override {
|
virtual std::any visit(WhileStmt &whileStmt, std::any param) override {
|
||||||
|
if (whileStmt.condition.get())
|
||||||
whileStmt.condition->accept(this, param);
|
whileStmt.condition->accept(this, param);
|
||||||
|
if (whileStmt.body.get())
|
||||||
for (auto &body : whileStmt.body) {
|
whileStmt.body->accept(this, param);
|
||||||
body->accept(this, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(PrimitiveTypeName &primitiveTypeName,
|
virtual std::any visit(NamedTypeName &namedTypeName,
|
||||||
std::any param) override {
|
std::any param) override {
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
@ -28,12 +27,17 @@ enum BinOp {
|
|||||||
class BinExpr : public Expr {
|
class BinExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
const BinOp op;
|
const BinOp op;
|
||||||
const std::shared_ptr<Expr> lhs, rhs;
|
std::unique_ptr<Expr> lhs, rhs;
|
||||||
|
|
||||||
BinExpr(LOC_ARG, const BinOp op, Expr *lhs, Expr *rhs)
|
BinExpr(LOC_ARG, const BinOp op, std::unique_ptr<Expr> lhs,
|
||||||
: Expr(sourceRange), op(op), lhs(lhs), rhs(rhs) {}
|
std::unique_ptr<Expr> rhs)
|
||||||
|
: Expr(sourceRange), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
BinExpr(LOC_ARG, const BinOp op, std::unique_ptr<Expr> &lhs,
|
||||||
|
std::unique_ptr<Expr> &rhs)
|
||||||
|
: Expr(sourceRange), op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {}
|
||||||
|
|
||||||
|
virtual boost::json::value toJson() const override;
|
||||||
static BinExpr *fromJson(boost::json::value json);
|
static BinExpr *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -9,17 +9,14 @@ namespace ast {
|
|||||||
|
|
||||||
class CallExpr : public Expr {
|
class CallExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> callee;
|
std::unique_ptr<Expr> callee;
|
||||||
std::vector<std::shared_ptr<Expr>> args;
|
std::vector<std::unique_ptr<Expr>> args;
|
||||||
|
|
||||||
CallExpr(LOC_ARG, Expr *callee, std::vector<Expr *> args)
|
CallExpr(LOC_ARG, std::unique_ptr<Expr> callee,
|
||||||
: Expr(sourceRange), callee(callee), args() {
|
std::vector<std::unique_ptr<Expr>> args)
|
||||||
for (auto &arg : args) {
|
: Expr(sourceRange), callee(std::move(callee)), args(std::move(args)) {}
|
||||||
this->args.push_back(std::shared_ptr<Expr>(arg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static CallExpr *fromJson(boost::json::value json);
|
static CallExpr *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
class CastExpr : public Expr {
|
class CastExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> value;
|
std::unique_ptr<Expr> value;
|
||||||
const std::shared_ptr<TypeName> typeName;
|
std::unique_ptr<TypeName> typeName;
|
||||||
|
|
||||||
CastExpr(LOC_ARG, Expr *value, TypeName *typeName)
|
CastExpr(LOC_ARG, std::unique_ptr<Expr> value,
|
||||||
: Expr(sourceRange), value(value), typeName(typeName) {}
|
std::unique_ptr<TypeName> typeName)
|
||||||
|
: Expr(sourceRange), value(std::move(value)),
|
||||||
|
typeName(std::move(typeName)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static CastExpr *fromJson(boost::json::value json);
|
static CastExpr *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -14,7 +14,7 @@ public:
|
|||||||
Identifier(LOC_ARG, const std::string &name)
|
Identifier(LOC_ARG, const std::string &name)
|
||||||
: Expr(sourceRange), name(name) {}
|
: Expr(sourceRange), name(name) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static Identifier *fromJson(boost::json::value json);
|
static Identifier *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
@ -11,21 +10,17 @@ class FnParam;
|
|||||||
|
|
||||||
class LambdaExpr : public Expr {
|
class LambdaExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
std::vector<std::shared_ptr<FnParam>> params;
|
std::vector<std::unique_ptr<FnParam>> params;
|
||||||
std::vector<std::shared_ptr<Expr>> body;
|
std::unique_ptr<TypeName> returnTypeName;
|
||||||
|
std::unique_ptr<Block> body;
|
||||||
|
|
||||||
LambdaExpr(LOC_ARG, std::vector<FnParam *> params, std::vector<Expr *> body)
|
LambdaExpr(LOC_ARG, std::vector<std::unique_ptr<FnParam>> params,
|
||||||
: Expr(sourceRange), params(), body() {
|
std::unique_ptr<TypeName> returnTypeName,
|
||||||
for (auto ¶m : params) {
|
std::unique_ptr<Block> body)
|
||||||
this->params.push_back(std::shared_ptr<FnParam>(param));
|
: Expr(sourceRange), params(std::move(params)),
|
||||||
}
|
returnTypeName(std::move(returnTypeName)), body(std::move(body)) {}
|
||||||
|
|
||||||
for (auto &expr : body) {
|
virtual boost::json::value toJson() const override;
|
||||||
this->body.push_back(std::shared_ptr<Expr>(expr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
|
||||||
static LambdaExpr *fromJson(boost::json::value json);
|
static LambdaExpr *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
@ -15,12 +14,12 @@ enum UnOp {
|
|||||||
class UnExpr : public Expr {
|
class UnExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
const UnOp op;
|
const UnOp op;
|
||||||
const std::shared_ptr<Expr> expr;
|
std::unique_ptr<Expr> expr;
|
||||||
|
|
||||||
UnExpr(LOC_ARG, const UnOp op, Expr *expr)
|
UnExpr(LOC_ARG, const UnOp op, std::unique_ptr<Expr> expr)
|
||||||
: Expr(sourceRange), op(op), expr(expr) {}
|
: Expr(sourceRange), op(op), expr(std::move(expr)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static UnExpr *fromJson(boost::json::value json);
|
static UnExpr *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
@ -11,7 +10,7 @@ namespace ast {
|
|||||||
// public:
|
// public:
|
||||||
// NullValue(LOC_ARG) : Expr(sourceRange) {}
|
// NullValue(LOC_ARG) : Expr(sourceRange) {}
|
||||||
|
|
||||||
// virtual boost::json::value toJson() override;
|
// virtual boost::json::value toJson() const override;
|
||||||
// static std::unique_ptr<NullValue> fromJson(boost::json::value json);
|
// static std::unique_ptr<NullValue> fromJson(boost::json::value json);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
@ -21,7 +20,7 @@ public:
|
|||||||
|
|
||||||
IntValue(LOC_ARG, int64_t value) : Expr(sourceRange), value(value) {}
|
IntValue(LOC_ARG, int64_t value) : Expr(sourceRange), value(value) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static IntValue *fromJson(boost::json::value json);
|
static IntValue *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
@ -35,7 +34,7 @@ public:
|
|||||||
|
|
||||||
FloatValue(LOC_ARG, double value) : Expr(sourceRange), value(value) {}
|
FloatValue(LOC_ARG, double value) : Expr(sourceRange), value(value) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static FloatValue *fromJson(boost::json::value json);
|
static FloatValue *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -12,7 +12,7 @@ public:
|
|||||||
Import(LOC_ARG, const std::string &moduleName)
|
Import(LOC_ARG, const std::string &moduleName)
|
||||||
: ASTNode(sourceRange), moduleName(moduleName) {}
|
: ASTNode(sourceRange), moduleName(moduleName) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static Import *fromJson(boost::json::value json);
|
static Import *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -11,22 +11,16 @@ class Import;
|
|||||||
class Module : public ASTNode {
|
class Module : public ASTNode {
|
||||||
public:
|
public:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
std::vector<std::shared_ptr<Import>> imports;
|
std::vector<std::unique_ptr<Import>> imports;
|
||||||
std::vector<std::shared_ptr<Stmt>> stmts;
|
std::vector<std::unique_ptr<Stmt>> stmts;
|
||||||
|
|
||||||
Module(LOC_ARG, const std::string &name, const std::vector<Import *> &imports,
|
Module(LOC_ARG, const std::string &name,
|
||||||
const std::vector<Stmt *> &stmts)
|
std::vector<std::unique_ptr<Import>> imports,
|
||||||
: ASTNode(sourceRange), name(name), imports(), stmts() {
|
std::vector<std::unique_ptr<Stmt>> stmts)
|
||||||
for (auto &import : imports) {
|
: ASTNode(sourceRange), name(name), imports(std::move(imports)),
|
||||||
this->imports.push_back(std::shared_ptr<Import>(import));
|
stmts(std::move(stmts)) {}
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &stmt : stmts) {
|
virtual boost::json::value toJson() const override;
|
||||||
this->stmts.push_back(std::shared_ptr<Stmt>(stmt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
|
||||||
static Module *fromJson(boost::json::value json);
|
static Module *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -2,20 +2,19 @@
|
|||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
class AssignStmt : public Stmt {
|
class AssignStmt : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> lval;
|
std::unique_ptr<Expr> lval;
|
||||||
const std::shared_ptr<Expr> rval;
|
std::unique_ptr<Expr> rval;
|
||||||
|
|
||||||
AssignStmt(LOC_ARG, Expr *lval, Expr *rval)
|
AssignStmt(LOC_ARG, std::unique_ptr<Expr> lval, std::unique_ptr<Expr> rval)
|
||||||
: Stmt(sourceRange), lval(lval), rval(rval) {}
|
: Stmt(sourceRange), lval(std::move(lval)), rval(std::move(rval)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static AssignStmt *fromJson(boost::json::value json);
|
static AssignStmt *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
24
compiler/include/AST/Stmt/Block.h
Normal file
24
compiler/include/AST/Stmt/Block.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AST/Base.h"
|
||||||
|
|
||||||
|
namespace plsm {
|
||||||
|
namespace ast {
|
||||||
|
|
||||||
|
class Block : public ASTNode {
|
||||||
|
public:
|
||||||
|
std::vector<std::unique_ptr<Stmt>> stmts;
|
||||||
|
|
||||||
|
Block(LOC_ARG, std::vector<std::unique_ptr<Stmt>> stmts)
|
||||||
|
: ASTNode(sourceRange), stmts(std::move(stmts)) {}
|
||||||
|
|
||||||
|
virtual boost::json::value toJson() const override;
|
||||||
|
static Block *fromJson(boost::json::value json);
|
||||||
|
|
||||||
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
return visitor->visit(*this, param);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ast
|
||||||
|
} // namespace plsm
|
@ -7,11 +7,12 @@ namespace plsm {
|
|||||||
namespace ast {
|
namespace ast {
|
||||||
class ExprStmt : public Stmt {
|
class ExprStmt : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> expr;
|
std::unique_ptr<Expr> expr;
|
||||||
|
|
||||||
ExprStmt(LOC_ARG, Expr *expr) : Stmt(sourceRange), expr(expr) {}
|
ExprStmt(LOC_ARG, std::unique_ptr<Expr> expr)
|
||||||
|
: Stmt(sourceRange), expr(std::move(expr)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static ExprStmt *fromJson(boost::json::value json);
|
static ExprStmt *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -11,14 +11,14 @@ namespace ast {
|
|||||||
class FnParam : public ASTNode {
|
class FnParam : public ASTNode {
|
||||||
public:
|
public:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
const std::shared_ptr<TypeName> typeName;
|
std::unique_ptr<TypeName> typeName;
|
||||||
|
|
||||||
std::shared_ptr<Symbol> symbol;
|
std::shared_ptr<Symbol> symbol;
|
||||||
|
|
||||||
FnParam(LOC_ARG, const std::string &name, TypeName *typeName)
|
FnParam(LOC_ARG, const std::string &name, std::unique_ptr<TypeName> typeName)
|
||||||
: ASTNode(sourceRange), name(name), typeName(typeName) {}
|
: ASTNode(sourceRange), name(name), typeName(std::move(typeName)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static FnParam *fromJson(boost::json::value json);
|
static FnParam *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
@ -29,26 +29,19 @@ public:
|
|||||||
class FnDecl : public Stmt {
|
class FnDecl : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
std::vector<std::shared_ptr<FnParam>> params;
|
std::vector<std::unique_ptr<FnParam>> params;
|
||||||
const std::shared_ptr<TypeName> returnTypeName;
|
std::unique_ptr<TypeName> returnTypeName;
|
||||||
std::vector<std::shared_ptr<Stmt>> body;
|
std::unique_ptr<Block> body;
|
||||||
|
|
||||||
std::shared_ptr<Symbol> symbol;
|
std::shared_ptr<Symbol> symbol;
|
||||||
|
|
||||||
FnDecl(LOC_ARG, const std::string &name, const std::vector<FnParam *> ¶ms,
|
FnDecl(LOC_ARG, const std::string &name,
|
||||||
TypeName *returnTypeName, const std::vector<Stmt *> &body)
|
std::vector<std::unique_ptr<FnParam>> params,
|
||||||
: Stmt(sourceRange), name(name), params(), returnTypeName(returnTypeName),
|
std::unique_ptr<TypeName> returnTypeName, std::unique_ptr<Block> body)
|
||||||
body() {
|
: Stmt(sourceRange), name(name), params(std::move(params)),
|
||||||
for (auto ¶m : params) {
|
returnTypeName(std::move(returnTypeName)), body(std::move(body)) {}
|
||||||
this->params.push_back(std::shared_ptr<FnParam>(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &stmt : body) {
|
virtual boost::json::value toJson() const override;
|
||||||
this->body.push_back(std::shared_ptr<Stmt>(stmt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
|
||||||
static FnDecl *fromJson(boost::json::value json);
|
static FnDecl *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -2,29 +2,21 @@
|
|||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
class IfStmt : public Stmt {
|
class IfStmt : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> condition;
|
std::unique_ptr<Expr> condition;
|
||||||
std::vector<std::shared_ptr<Stmt>> ifBody, elseBody;
|
std::unique_ptr<Block> ifBody, elseBody;
|
||||||
|
|
||||||
IfStmt(LOC_ARG, Expr *condition, const std::vector<Stmt *> &ifBody,
|
IfStmt(LOC_ARG, std::unique_ptr<Expr> condition,
|
||||||
const std::vector<Stmt *> &elseBody)
|
std::unique_ptr<Block> ifBody, std::unique_ptr<Block> elseBody)
|
||||||
: Stmt(sourceRange), condition(condition) {
|
: Stmt(sourceRange), condition(std::move(condition)),
|
||||||
for (auto &stmt : ifBody) {
|
ifBody(std::move(ifBody)), elseBody(std::move(elseBody)) {}
|
||||||
this->ifBody.push_back(std::shared_ptr<Stmt>(stmt));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &stmt : elseBody) {
|
virtual boost::json::value toJson() const override;
|
||||||
this->elseBody.push_back(std::shared_ptr<Stmt>(stmt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
|
||||||
static IfStmt *fromJson(boost::json::value json);
|
static IfStmt *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -7,11 +7,12 @@ namespace plsm {
|
|||||||
namespace ast {
|
namespace ast {
|
||||||
class RetStmt : public Stmt {
|
class RetStmt : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> value;
|
std::unique_ptr<Expr> value;
|
||||||
|
|
||||||
RetStmt(LOC_ARG, Expr *value) : Stmt(sourceRange), value(value) {}
|
RetStmt(LOC_ARG, std::unique_ptr<Expr> value)
|
||||||
|
: Stmt(sourceRange), value(std::move(value)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static RetStmt *fromJson(boost::json::value json);
|
static RetStmt *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -10,14 +10,14 @@ namespace ast {
|
|||||||
class VarDecl : public Stmt {
|
class VarDecl : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
const std::shared_ptr<TypeName> typeName;
|
std::unique_ptr<TypeName> typeName;
|
||||||
|
|
||||||
std::shared_ptr<Symbol> symbol;
|
std::shared_ptr<Symbol> symbol;
|
||||||
|
|
||||||
VarDecl(LOC_ARG, const std::string &name, TypeName *typeName)
|
VarDecl(LOC_ARG, const std::string &name, std::unique_ptr<TypeName> typeName)
|
||||||
: Stmt(sourceRange), name(name), typeName(typeName) {}
|
: Stmt(sourceRange), name(name), typeName(std::move(typeName)) {}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static VarDecl *fromJson(boost::json::value json);
|
static VarDecl *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
@ -2,28 +2,26 @@
|
|||||||
|
|
||||||
#include "AST/Base.h"
|
#include "AST/Base.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
class WhileStmt : public Stmt {
|
class WhileStmt : public Stmt {
|
||||||
public:
|
public:
|
||||||
const std::shared_ptr<Expr> condition;
|
std::unique_ptr<Expr> condition;
|
||||||
std::vector<std::shared_ptr<Stmt>> body;
|
std::unique_ptr<Block> body;
|
||||||
|
|
||||||
WhileStmt(LOC_ARG, Expr *condition, const std::vector<Stmt *> &body)
|
WhileStmt(LOC_ARG, std::unique_ptr<Expr> condition,
|
||||||
: Stmt(sourceRange), condition(condition) {
|
std::unique_ptr<Block> body)
|
||||||
for (auto &stmt : body) {
|
: Stmt(sourceRange), condition(std::move(condition)),
|
||||||
this->body.push_back(std::shared_ptr<Stmt>(stmt));
|
body(std::move(body)) {}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual boost::json::value toJson() const override;
|
||||||
static WhileStmt *fromJson(boost::json::value json);
|
static WhileStmt *fromJson(boost::json::value json);
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
return visitor->visit(*this, param);
|
return visitor->visit(*this, param);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace plsm
|
} // namespace plsm
|
||||||
|
@ -11,14 +11,36 @@ public:
|
|||||||
std::vector<std::shared_ptr<Type>> paramTypes;
|
std::vector<std::shared_ptr<Type>> paramTypes;
|
||||||
const std::shared_ptr<Type> returnType;
|
const std::shared_ptr<Type> returnType;
|
||||||
|
|
||||||
FunctionType(const std::vector<Type *> ¶mTypes, Type *returnType)
|
FunctionType(std::vector<std::shared_ptr<Type>> paramTypes,
|
||||||
: Type(), returnType(returnType) {
|
std::shared_ptr<Type> returnType)
|
||||||
for (auto ¶mType : paramTypes) {
|
: Type(), paramTypes(paramTypes), returnType(returnType) {}
|
||||||
this->paramTypes.push_back(std::shared_ptr<Type>(paramType));
|
|
||||||
}
|
virtual TypeName *toTypeName() override;
|
||||||
|
|
||||||
|
virtual bool operator==(const Type &other) override {
|
||||||
|
if (const FunctionType *ft = dynamic_cast<const FunctionType *>(&other)) {
|
||||||
|
Type &lhsType = *returnType;
|
||||||
|
Type &rhsType = *ft->returnType;
|
||||||
|
if (lhsType != rhsType)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (paramTypes.size() != ft->paramTypes.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (ssize_t i = 0; i < paramTypes.size(); i++) {
|
||||||
|
Type &lhsType = *paramTypes[i];
|
||||||
|
Type &rhsType = *ft->paramTypes[i];
|
||||||
|
if (lhsType != rhsType)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual boost::json::value toJson() const override;
|
||||||
static FunctionType *fromJson(boost::json::value json);
|
static FunctionType *fromJson(boost::json::value json);
|
||||||
};
|
};
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -11,10 +11,17 @@ public:
|
|||||||
|
|
||||||
PrimitiveType(const std::string &name) : Type(), name(name) {}
|
PrimitiveType(const std::string &name) : Type(), name(name) {}
|
||||||
|
|
||||||
bool operator==(const PrimitiveType &other) { return name == other.name; }
|
virtual TypeName *toTypeName() override;
|
||||||
bool operator!=(const PrimitiveType &other) { return !(*this == other); }
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
virtual bool operator==(const Type &other) override {
|
||||||
|
if (const PrimitiveType *pt = dynamic_cast<const PrimitiveType *>(&other)) {
|
||||||
|
return name == pt->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual boost::json::value toJson() const override;
|
||||||
static PrimitiveType *fromJson(boost::json::value json);
|
static PrimitiveType *fromJson(boost::json::value json);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
27
compiler/include/AST/TypeName/NamedTypeName.h
Normal file
27
compiler/include/AST/TypeName/NamedTypeName.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AST/Base.h"
|
||||||
|
|
||||||
|
namespace plsm {
|
||||||
|
namespace ast {
|
||||||
|
|
||||||
|
class NamedTypeName : public TypeName {
|
||||||
|
public:
|
||||||
|
const std::string name;
|
||||||
|
|
||||||
|
NamedTypeName(LOC_ARG, const std::string &name)
|
||||||
|
: TypeName(sourceRange), name(name) {}
|
||||||
|
|
||||||
|
bool operator==(const NamedTypeName &other) { return name == other.name; }
|
||||||
|
bool operator!=(const NamedTypeName &other) { return !(*this == other); }
|
||||||
|
|
||||||
|
virtual boost::json::value toJson() const override;
|
||||||
|
static NamedTypeName *fromJson(boost::json::value json);
|
||||||
|
|
||||||
|
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
||||||
|
return visitor->visit(*this, param);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ast
|
||||||
|
} // namespace plsm
|
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AST/Base.h"
|
|
||||||
|
|
||||||
namespace plsm {
|
|
||||||
namespace ast {
|
|
||||||
|
|
||||||
class PrimitiveTypeName : public TypeName {
|
|
||||||
public:
|
|
||||||
const std::string name;
|
|
||||||
|
|
||||||
PrimitiveTypeName(LOC_ARG, const std::string &name)
|
|
||||||
: TypeName(sourceRange), name(name) {}
|
|
||||||
|
|
||||||
bool operator==(const PrimitiveTypeName &other) { return name == other.name; }
|
|
||||||
bool operator!=(const PrimitiveTypeName &other) { return !(*this == other); }
|
|
||||||
|
|
||||||
virtual boost::json::value toJson() override;
|
|
||||||
static PrimitiveTypeName *fromJson(boost::json::value json);
|
|
||||||
|
|
||||||
virtual std::any accept(ASTVisitor *visitor, std::any param) override {
|
|
||||||
return visitor->visit(*this, param);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ast
|
|
||||||
} // namespace plsm
|
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
|
|
||||||
void performNameAnalysis(std::shared_ptr<ast::Module> module);
|
void performNameAnalysis(std::unique_ptr<ast::Module> &module);
|
||||||
|
void performTypeAnalysis(std::unique_ptr<ast::Module> &module);
|
||||||
|
|
||||||
}
|
} // namespace plsm
|
||||||
|
13
compiler/include/Errors.h
Normal file
13
compiler/include/Errors.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace plsm {
|
||||||
|
namespace errors {
|
||||||
|
|
||||||
|
void put(const std::string &msg);
|
||||||
|
std::vector<std::string> get();
|
||||||
|
|
||||||
|
} // namespace errors
|
||||||
|
} // namespace plsm
|
@ -6,6 +6,6 @@
|
|||||||
#include "AST/AST.h"
|
#include "AST/AST.h"
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
std::shared_ptr<ast::Module> parse(const std::string &file,
|
std::unique_ptr<ast::Module> parse(const std::string &file,
|
||||||
const std::string &input);
|
const std::string &input);
|
||||||
}
|
}
|
||||||
|
10
compiler/include/Terminal.h
Normal file
10
compiler/include/Terminal.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace terminal {
|
||||||
|
|
||||||
|
const auto reset = "\x1B[0m";
|
||||||
|
const auto cyan = "\x1B[36m";
|
||||||
|
const auto red = "\x1B[31m";
|
||||||
|
const auto yellow = "\x1B[33m";
|
||||||
|
|
||||||
|
} // namespace terminal
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -5,7 +7,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
template <typename T> auto mapToJson(const std::vector<T> &vector) {
|
template <typename T> inline auto mapToJson(const std::vector<T> &vector) {
|
||||||
boost::json::array result(vector.size());
|
boost::json::array result(vector.size());
|
||||||
for (size_t i = 0; i < vector.size(); i++)
|
for (size_t i = 0; i < vector.size(); i++)
|
||||||
result[i] = vector[i]->toJson();
|
result[i] = vector[i]->toJson();
|
||||||
@ -13,12 +15,30 @@ template <typename T> auto mapToJson(const std::vector<T> &vector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename Mapper>
|
template <typename T, typename Mapper>
|
||||||
auto mapToJson(const std::vector<T> &vector, const Mapper &mapper) {
|
inline auto mapToJson(const std::vector<T> &vector, const Mapper &mapper) {
|
||||||
boost::json::array result(vector.size());
|
boost::json::array result(vector.size());
|
||||||
for (size_t i = 0; i < vector.size(); i++)
|
for (size_t i = 0; i < vector.size(); i++)
|
||||||
result[i] = mapper(vector[i]);
|
result[i] = mapper(vector[i]);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename B, typename A> inline bool is(const A *value) {
|
||||||
|
return value && dynamic_cast<const B *>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A, typename B>
|
||||||
|
inline std::unique_ptr<A> ptrcast(std::unique_ptr<B> &ptr) {
|
||||||
|
return std::unique_ptr<A>(static_cast<A *>(ptr.release()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A, typename B>
|
||||||
|
inline std::shared_ptr<A> ptrcast(std::shared_ptr<B> &ptr) {
|
||||||
|
return std::static_pointer_cast<A>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <typename B, typename A> inline bool is(const A &value) {
|
||||||
|
// return dynamic_cast<const B *>(&value) != nullptr;
|
||||||
|
// }
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
} // namespace plsm
|
} // namespace plsm
|
||||||
|
242
compiler/plsm.g4
242
compiler/plsm.g4
@ -2,189 +2,199 @@ grammar plsm;
|
|||||||
|
|
||||||
@parser::header {
|
@parser::header {
|
||||||
#include "AST/AST.h"
|
#include "AST/AST.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
using namespace plsm::utils;
|
||||||
using namespace plsm::ast;
|
using namespace plsm::ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
@parser::members {
|
@parser::members {
|
||||||
|
std::string filename, sourceText;
|
||||||
std::string filename;
|
|
||||||
|
|
||||||
void setFileName(const std::string &filename) { this->filename = filename; }
|
void setFileName(const std::string &filename) { this->filename = filename; }
|
||||||
|
void setSourceText(const std::string &sourceText) { this->sourceText = sourceText; }
|
||||||
|
|
||||||
inline SourceRange getSourceRange(antlr4::ParserRuleContext *ctx) {
|
inline SourceRange getSourceRange(antlr4::ParserRuleContext *ctx) {
|
||||||
if (!ctx->getStart() || !ctx->getStop()) {
|
auto start = ctx->start;
|
||||||
return SourceRange::unknown();
|
auto stop = getCurrentToken();
|
||||||
}
|
|
||||||
|
|
||||||
return SourceRange(
|
auto startPos = std::pair<size_t, size_t>(start->getLine(),
|
||||||
filename, ctx->getText(),
|
start->getCharPositionInLine());
|
||||||
std::pair<size_t, size_t>(ctx->getStart()->getLine(),
|
auto stopPos = std::pair<size_t, size_t>(stop->getLine(),
|
||||||
ctx->getStart()->getCharPositionInLine()),
|
stop->getCharPositionInLine());
|
||||||
std::pair<size_t, size_t>(ctx->getStop()->getLine(),
|
|
||||||
ctx->getStop()->getCharPositionInLine()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto text = sourceText.substr(
|
||||||
|
start->getStartIndex(), stop->getStartIndex() - start->getStartIndex());
|
||||||
|
text = boost::trim_copy(text);
|
||||||
|
|
||||||
|
// std::cout << "text: `" << text << "`" << std::endl;
|
||||||
|
|
||||||
|
return SourceRange(filename, text, startPos, stopPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module
|
module
|
||||||
returns[Module *ast]: (stmts += topLevelStmt)* {
|
returns[std::unique_ptr<Module> ast]: (stmts += topLevelStmt)* EOF {
|
||||||
std::vector<Stmt *> stmts;
|
std::vector<std::unique_ptr<Stmt>> stmts;
|
||||||
for (auto &stmt : $ctx->stmts) {
|
for (auto &stmt : $ctx->stmts) {
|
||||||
stmts.push_back(stmt->ast);
|
stmts.push_back(std::move(stmt->ast));
|
||||||
}
|
}
|
||||||
|
|
||||||
$ast = new Module(getSourceRange($ctx), "default", std::vector<Import *>(), stmts);
|
$ast = std::make_unique<Module>(getSourceRange($ctx), "default", std::vector<std::unique_ptr<Import>>(), std::move(stmts));
|
||||||
};
|
};
|
||||||
|
|
||||||
topLevelStmt
|
topLevelStmt
|
||||||
returns[Stmt *ast]:
|
returns[std::unique_ptr<Stmt> ast]:
|
||||||
varDecl {
|
varDecl {
|
||||||
$ast = $ctx->varDecl()->ast;
|
$ast = ptrcast<Stmt>($ctx->varDecl()->ast);
|
||||||
}
|
}
|
||||||
| fnDecl {
|
| fnDecl {
|
||||||
$ast = $ctx->fnDecl()->ast;
|
$ast = ptrcast<Stmt>($ctx->fnDecl()->ast);
|
||||||
|
};
|
||||||
|
|
||||||
|
block
|
||||||
|
returns[std::unique_ptr<Block> ast]:
|
||||||
|
(stmts += stmt)* {
|
||||||
|
std::vector<std::unique_ptr<Stmt>> stmts;
|
||||||
|
for (auto &stmt : $ctx->stmts) {
|
||||||
|
stmts.push_back(std::move(stmt->ast));
|
||||||
|
}
|
||||||
|
|
||||||
|
$ast = std::make_unique<Block>(getSourceRange($ctx), std::move(stmts));
|
||||||
|
};
|
||||||
|
|
||||||
|
singleStmtBlock
|
||||||
|
returns[std::unique_ptr<Block> ast]:
|
||||||
|
stmt {
|
||||||
|
std::vector<std::unique_ptr<Stmt>> stmts;
|
||||||
|
stmts.push_back(std::move($ctx->stmt()->ast));
|
||||||
|
$ast = std::make_unique<Block>(getSourceRange($ctx), std::move(stmts));
|
||||||
};
|
};
|
||||||
|
|
||||||
stmt
|
stmt
|
||||||
returns[Stmt *ast]:
|
returns[std::unique_ptr<Stmt> ast]:
|
||||||
exprStmt {
|
exprStmt {
|
||||||
$ast = $ctx->exprStmt()->ast;
|
$ast = ptrcast<Stmt>($ctx->exprStmt()->ast);
|
||||||
}
|
}
|
||||||
| varDecl {
|
| varDecl {
|
||||||
$ast = $ctx->varDecl()->ast;
|
$ast = ptrcast<Stmt>($ctx->varDecl()->ast);
|
||||||
}
|
}
|
||||||
| retStmt {
|
| retStmt {
|
||||||
$ast = $ctx->retStmt()->ast;
|
$ast = ptrcast<Stmt>($ctx->retStmt()->ast);
|
||||||
}
|
}
|
||||||
| assignStmt {
|
| assignStmt {
|
||||||
$ast = $ctx->assignStmt()->ast;
|
$ast = ptrcast<Stmt>($ctx->assignStmt()->ast);
|
||||||
}
|
}
|
||||||
| implDeclAssignStmt {
|
| implDeclAssignStmt {
|
||||||
$ast = $ctx->implDeclAssignStmt()->ast;
|
$ast = ptrcast<Stmt>($ctx->implDeclAssignStmt()->ast);
|
||||||
}
|
}
|
||||||
| ifStmt {
|
| ifStmt {
|
||||||
$ast = $ctx->ifStmt()->ast;
|
$ast = ptrcast<Stmt>($ctx->ifStmt()->ast);
|
||||||
}
|
}
|
||||||
| whileStmt {
|
| whileStmt {
|
||||||
$ast = $ctx->whileStmt()->ast;
|
$ast = ptrcast<Stmt>($ctx->whileStmt()->ast);
|
||||||
};
|
};
|
||||||
|
|
||||||
whileStmt
|
whileStmt
|
||||||
returns[WhileStmt *ast]:
|
returns[std::unique_ptr<WhileStmt> ast]:
|
||||||
'while' '(' condition = expr ')' (
|
'while' '(' condition = expr ')' (
|
||||||
'{' (stmts += stmt)* '}'
|
'{' block '}'
|
||||||
| singleStmt = stmt
|
| singleStmtBlock
|
||||||
) {
|
) {
|
||||||
auto cond = $ctx->condition->ast;
|
std::unique_ptr<Block> body;
|
||||||
|
if ($ctx->block()) body = std::move($ctx->block()->ast);
|
||||||
|
else body = std::move($ctx->singleStmtBlock()->ast);
|
||||||
|
|
||||||
std::vector<Stmt *> body;
|
$ast = std::make_unique<WhileStmt>(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(body));
|
||||||
for (auto &stmt : $ctx->stmts) {
|
|
||||||
body.push_back(stmt->ast);
|
|
||||||
}
|
|
||||||
if ($ctx->singleStmt) body.push_back($ctx->singleStmt->ast);
|
|
||||||
|
|
||||||
$ast = new WhileStmt(getSourceRange($ctx), cond, body);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ifStmt
|
ifStmt
|
||||||
returns[IfStmt *ast]:
|
returns[std::unique_ptr<IfStmt> ast]:
|
||||||
'if' '(' condition = expr ')' (
|
'if' '(' condition = expr ')' (
|
||||||
'{' (ifStmts += stmt)* '}'
|
'{' ifBlock = block '}'
|
||||||
| ifSingleStmt = stmt
|
| ifSingleBlock = singleStmtBlock
|
||||||
) (
|
) (
|
||||||
'else' (
|
'else' (
|
||||||
'{' (elseStmts += stmt)* '}'
|
'{' elseBlock = block '}'
|
||||||
| elseSingleStmt = stmt
|
| elseSingleBlock = singleStmtBlock
|
||||||
)
|
)
|
||||||
)? {
|
)? {
|
||||||
auto cond = $ctx->condition->ast;
|
std::unique_ptr<Block> ifBody;
|
||||||
|
if ($ctx->ifBlock) ifBody = std::move($ctx->ifBlock->ast);
|
||||||
|
else ifBody = std::move($ctx->ifSingleBlock->ast);
|
||||||
|
|
||||||
std::vector<Stmt *> ifBody;
|
std::unique_ptr<Block> elseBody;
|
||||||
for (auto &stmt : $ctx->ifStmts) {
|
if ($ctx->elseBlock) elseBody = std::move($ctx->elseBlock->ast);
|
||||||
ifBody.push_back(stmt->ast);
|
else if ($ctx->elseSingleBlock) elseBody = std::move($ctx->elseSingleBlock->ast);
|
||||||
}
|
else elseBody = std::make_unique<Block>(SourceRange::unknown(), std::vector<std::unique_ptr<Stmt>>());
|
||||||
if ($ctx->ifSingleStmt) ifBody.push_back($ctx->ifSingleStmt->ast);
|
|
||||||
|
|
||||||
|
$ast = std::make_unique<IfStmt>(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(ifBody), std::move(elseBody));
|
||||||
std::vector<Stmt *> elseBody;
|
|
||||||
for (auto &stmt : $ctx->elseStmts) {
|
|
||||||
elseBody.push_back(stmt->ast);
|
|
||||||
}
|
|
||||||
if ($ctx->elseSingleStmt) elseBody.push_back($ctx->elseSingleStmt->ast);
|
|
||||||
|
|
||||||
$ast = new IfStmt(getSourceRange($ctx), cond, ifBody, elseBody);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
implDeclAssignStmt
|
implDeclAssignStmt
|
||||||
returns[Stmt *ast]:
|
returns[std::unique_ptr<Stmt> ast]:
|
||||||
IDENTIFIER ':=' expr {
|
IDENTIFIER ':=' expr {
|
||||||
// TODO
|
// TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
assignStmt
|
assignStmt
|
||||||
returns[AssignStmt *ast]:
|
returns[std::unique_ptr<AssignStmt> ast]:
|
||||||
lval = expr '=' rval = expr {
|
lval = expr '=' rval = expr ';' {
|
||||||
$ast = new AssignStmt(getSourceRange($ctx), $ctx->lval->ast, $ctx->rval->ast);
|
$ast = std::make_unique<AssignStmt>(getSourceRange($ctx), std::move($ctx->lval->ast), std::move($ctx->rval->ast));
|
||||||
};
|
};
|
||||||
|
|
||||||
retStmt
|
retStmt
|
||||||
returns[RetStmt *ast]:
|
returns[std::unique_ptr<RetStmt> ast]:
|
||||||
'ret' expr ';' {
|
'ret' expr ';' {
|
||||||
$ast = new RetStmt(getSourceRange($ctx), $ctx->expr()->ast);
|
$ast = std::make_unique<RetStmt>(getSourceRange($ctx), std::move($ctx->expr()->ast));
|
||||||
};
|
};
|
||||||
|
|
||||||
fnDecl
|
fnDecl
|
||||||
returns[FnDecl *ast]:
|
returns[std::unique_ptr<FnDecl> ast]:
|
||||||
'fun' name = IDENTIFIER '(' (
|
'fun' name = IDENTIFIER '(' (
|
||||||
params += fnParam (',' params += fnParam)*
|
params += fnParam (',' params += fnParam)*
|
||||||
)? ')' typeName '{' (stmts += stmt)* '}' {
|
)? ')' typeName '{' block '}' {
|
||||||
auto name = $ctx->name->getText();
|
auto name = $ctx->name->getText();
|
||||||
|
|
||||||
std::vector<FnParam *> params;
|
std::vector<std::unique_ptr<FnParam>> params;
|
||||||
for (auto ¶m : $ctx->params) {
|
for (auto ¶m : $ctx->params) {
|
||||||
params.push_back(param->ast);
|
params.push_back(std::move(param->ast));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto returnTypeName = $ctx->typeName()->ast;
|
$ast = std::make_unique<FnDecl>(getSourceRange($ctx), name, std::move(params), std::move($ctx->typeName()->ast), std::move($ctx->block()->ast));
|
||||||
|
|
||||||
std::vector<Stmt *> body;
|
|
||||||
for (auto &stmt : $ctx->stmts) {
|
|
||||||
body.push_back(stmt->ast);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ast = new FnDecl(getSourceRange($ctx), name, params, returnTypeName, body);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fnParam
|
fnParam
|
||||||
returns[FnParam *ast]:
|
returns[std::unique_ptr<FnParam> ast]:
|
||||||
IDENTIFIER typeName {
|
IDENTIFIER typeName {
|
||||||
$ast = new FnParam(getSourceRange($ctx), $ctx->IDENTIFIER()->getText(), $ctx->typeName()->ast);
|
$ast = std::make_unique<FnParam>(getSourceRange($ctx), $ctx->IDENTIFIER()->getText(), std::move($ctx->typeName()->ast));
|
||||||
};
|
};
|
||||||
|
|
||||||
varDecl
|
varDecl
|
||||||
returns[VarDecl *ast]:
|
returns[std::unique_ptr<VarDecl> ast]:
|
||||||
'var' IDENTIFIER ':' typeName ';' {
|
'var' IDENTIFIER ':' typeName ';' {
|
||||||
auto name = $ctx->IDENTIFIER()->getText();
|
auto name = $ctx->IDENTIFIER()->getText();
|
||||||
$ast = new VarDecl(getSourceRange($ctx), name, $ctx->typeName()->ast);
|
$ast = std::make_unique<VarDecl>(getSourceRange($ctx), name, std::move($ctx->typeName()->ast));
|
||||||
};
|
};
|
||||||
|
|
||||||
exprStmt
|
exprStmt
|
||||||
returns[ExprStmt *ast]:
|
returns[std::unique_ptr<ExprStmt> ast]:
|
||||||
expr ';' {
|
expr ';' {
|
||||||
$ast = new ExprStmt(getSourceRange($ctx), $ctx->expr()->ast);
|
$ast = std::make_unique<ExprStmt>(getSourceRange($ctx), std::move($ctx->expr()->ast));
|
||||||
};
|
};
|
||||||
|
|
||||||
expr
|
expr
|
||||||
returns[Expr *ast]:
|
returns[std::unique_ptr<Expr> ast]:
|
||||||
value = binaryExpr {
|
value = binaryExpr {
|
||||||
$ast = $ctx->value->ast;
|
$ast = std::move($ctx->value->ast);
|
||||||
};
|
};
|
||||||
|
|
||||||
binaryExpr
|
binaryExpr
|
||||||
returns[Expr *ast]:
|
returns[std::unique_ptr<Expr> ast]:
|
||||||
value = unaryExpr {
|
value = unaryExpr {
|
||||||
$ast = $ctx->value->ast;
|
$ast = std::move($ctx->value->ast);
|
||||||
}
|
}
|
||||||
| lhs = binaryExpr op = ('*' | '/' | '%') rhs = binaryExpr {
|
| lhs = binaryExpr op = ('*' | '/' | '%') rhs = binaryExpr {
|
||||||
auto opText = $ctx->op->getText();
|
auto opText = $ctx->op->getText();
|
||||||
@ -194,7 +204,8 @@ binaryExpr
|
|||||||
if (opText == "/") op = BinOp::DIV;
|
if (opText == "/") op = BinOp::DIV;
|
||||||
if (opText == "%") op = BinOp::MOD;
|
if (opText == "%") op = BinOp::MOD;
|
||||||
|
|
||||||
$ast = new BinExpr(getSourceRange($ctx), op, $ctx->lhs->ast, $ctx->rhs->ast);
|
auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
|
||||||
|
$ast = ptrcast<Expr>(binExpr);
|
||||||
}
|
}
|
||||||
| lhs = binaryExpr op = ('+' | '-') rhs = binaryExpr {
|
| lhs = binaryExpr op = ('+' | '-') rhs = binaryExpr {
|
||||||
auto opText = $ctx->op->getText();
|
auto opText = $ctx->op->getText();
|
||||||
@ -203,10 +214,12 @@ binaryExpr
|
|||||||
if (opText == "+") op = BinOp::ADD;
|
if (opText == "+") op = BinOp::ADD;
|
||||||
if (opText == "-") op = BinOp::SUB;
|
if (opText == "-") op = BinOp::SUB;
|
||||||
|
|
||||||
$ast = new BinExpr(getSourceRange($ctx), op, $ctx->lhs->ast, $ctx->rhs->ast);
|
auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
|
||||||
|
$ast = ptrcast<Expr>(binExpr);
|
||||||
}
|
}
|
||||||
| operand = binaryExpr 'as' typeName {
|
| operand = binaryExpr 'as' typeName {
|
||||||
$ast = new CastExpr(getSourceRange($ctx), $ctx->operand->ast, $ctx->typeName()->ast);
|
auto castExpr = std::make_unique<CastExpr>(getSourceRange($ctx), std::move($ctx->operand->ast), std::move($ctx->typeName()->ast));
|
||||||
|
$ast = ptrcast<Expr>(castExpr);
|
||||||
}
|
}
|
||||||
| lhs = binaryExpr op = (
|
| lhs = binaryExpr op = (
|
||||||
'=='
|
'=='
|
||||||
@ -226,37 +239,44 @@ binaryExpr
|
|||||||
if (opText == ">") op = BinOp::GT;
|
if (opText == ">") op = BinOp::GT;
|
||||||
if (opText == "<") op = BinOp::LT;
|
if (opText == "<") op = BinOp::LT;
|
||||||
|
|
||||||
$ast = new BinExpr(getSourceRange($ctx), op, $ctx->lhs->ast, $ctx->rhs->ast);
|
auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
|
||||||
|
$ast = ptrcast<Expr>(binExpr);
|
||||||
}
|
}
|
||||||
| lhs = binaryExpr '&&' rhs = binaryExpr {
|
| lhs = binaryExpr '&&' rhs = binaryExpr {
|
||||||
$ast = new BinExpr(getSourceRange($ctx), BinOp::AND, $ctx->lhs->ast, $ctx->rhs->ast);
|
auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), BinOp::AND, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
|
||||||
|
$ast = ptrcast<Expr>(binExpr);
|
||||||
}
|
}
|
||||||
| lhs = binaryExpr '||' rhs = binaryExpr {
|
| lhs = binaryExpr '||' rhs = binaryExpr {
|
||||||
$ast = new BinExpr(getSourceRange($ctx), BinOp::OR, $ctx->lhs->ast, $ctx->rhs->ast);
|
auto binExpr = std::make_unique<BinExpr>(getSourceRange($ctx), BinOp::OR, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast));
|
||||||
|
$ast = ptrcast<Expr>(binExpr);
|
||||||
};
|
};
|
||||||
|
|
||||||
unaryExpr
|
unaryExpr
|
||||||
returns[Expr *ast]:
|
returns[std::unique_ptr<Expr> ast]:
|
||||||
factorExpr {
|
factorExpr {
|
||||||
$ast = $ctx->factorExpr()->ast;
|
$ast = ptrcast<Expr>($ctx->factorExpr()->ast);
|
||||||
}
|
}
|
||||||
| functionCall {
|
| functionCall {
|
||||||
$ast = $ctx->functionCall()->ast;
|
$ast = ptrcast<Expr>($ctx->functionCall()->ast);
|
||||||
}
|
}
|
||||||
| '!' unaryExpr {
|
| '!' unaryExpr {
|
||||||
$ast = new UnExpr(getSourceRange($ctx), UnOp::NOT, $ctx->unaryExpr()->ast);
|
auto unExpr = std::make_unique<UnExpr>(getSourceRange($ctx), UnOp::NOT, std::move($ctx->unaryExpr()->ast));
|
||||||
|
$ast = ptrcast<Expr>(unExpr);
|
||||||
}
|
}
|
||||||
| '+' unaryExpr {
|
| '+' unaryExpr {
|
||||||
$ast = new UnExpr(getSourceRange($ctx), UnOp::POS, $ctx->unaryExpr()->ast);
|
auto unExpr = std::make_unique<UnExpr>(getSourceRange($ctx), UnOp::POS, std::move($ctx->unaryExpr()->ast));
|
||||||
|
$ast = ptrcast<Expr>(unExpr);
|
||||||
}
|
}
|
||||||
| '-' unaryExpr {
|
| '-' unaryExpr {
|
||||||
$ast = new UnExpr(getSourceRange($ctx), UnOp::NEG, $ctx->unaryExpr()->ast);
|
auto unExpr = std::make_unique<UnExpr>(getSourceRange($ctx), UnOp::NEG, std::move($ctx->unaryExpr()->ast));
|
||||||
|
$ast = ptrcast<Expr>(unExpr);
|
||||||
};
|
};
|
||||||
|
|
||||||
factorExpr
|
factorExpr
|
||||||
returns[Expr *ast]:
|
returns[std::unique_ptr<Expr> ast]:
|
||||||
IDENTIFIER {
|
IDENTIFIER {
|
||||||
$ast = new Identifier(getSourceRange($ctx), $ctx->IDENTIFIER()->getText());
|
auto id = std::make_unique<Identifier>(getSourceRange($ctx), $ctx->IDENTIFIER()->getText());
|
||||||
|
$ast = ptrcast<Expr>(id);
|
||||||
}
|
}
|
||||||
| INT {
|
| INT {
|
||||||
auto text = $ctx->INT()->getText();
|
auto text = $ctx->INT()->getText();
|
||||||
@ -275,7 +295,8 @@ factorExpr
|
|||||||
else
|
else
|
||||||
value = std::strtol(text.data(), NULL, 10);
|
value = std::strtol(text.data(), NULL, 10);
|
||||||
|
|
||||||
$ast = new IntValue(getSourceRange($ctx), value);
|
auto val = std::make_unique<IntValue>(getSourceRange($ctx), value);
|
||||||
|
$ast = ptrcast<Expr>(val);
|
||||||
}
|
}
|
||||||
| FLOAT {
|
| FLOAT {
|
||||||
auto text = $ctx->FLOAT()->getText();
|
auto text = $ctx->FLOAT()->getText();
|
||||||
@ -286,32 +307,35 @@ factorExpr
|
|||||||
text = "0" + text;
|
text = "0" + text;
|
||||||
|
|
||||||
double value = std::strtod(text.data(), NULL);
|
double value = std::strtod(text.data(), NULL);
|
||||||
$ast = new FloatValue(getSourceRange($ctx), value);
|
auto val = std::make_unique<FloatValue>(getSourceRange($ctx), value);
|
||||||
|
$ast = ptrcast<Expr>(val);
|
||||||
}
|
}
|
||||||
| BOOL {
|
| BOOL {
|
||||||
auto text = $ctx->BOOL()->getText();
|
auto text = $ctx->BOOL()->getText();
|
||||||
$ast = new IntValue(getSourceRange($ctx), text == "true" ? 1 : 0);
|
auto val = std::make_unique<IntValue>(getSourceRange($ctx), text == "true" ? 1 : 0);
|
||||||
|
$ast = ptrcast<Expr>(val);
|
||||||
}
|
}
|
||||||
| '(' expr ')' {
|
| '(' expr ')' {
|
||||||
$ast = $ctx->expr()->ast;
|
$ast = std::move($ctx->expr()->ast);
|
||||||
};
|
};
|
||||||
|
|
||||||
functionCall
|
functionCall
|
||||||
returns[Expr *ast]:
|
returns[std::unique_ptr<CallExpr> ast]:
|
||||||
callee = factorExpr '(' (args += expr (',' args += expr)*)? ')' {
|
callee = factorExpr '(' (args += expr (',' args += expr)*)? ')' {
|
||||||
std::vector<Expr *> args;
|
std::vector<std::unique_ptr<Expr>> args;
|
||||||
for (auto &arg : $ctx->args) {
|
for (auto &arg : $ctx->args) {
|
||||||
args.push_back(arg->ast);
|
args.push_back(std::move(arg->ast));
|
||||||
}
|
}
|
||||||
|
|
||||||
$ast = new CallExpr(getSourceRange($ctx), $ctx->callee->ast, args);
|
$ast = std::make_unique<CallExpr>(getSourceRange($ctx), std::move($ctx->callee->ast), std::move(args));
|
||||||
};
|
};
|
||||||
|
|
||||||
typeName
|
typeName
|
||||||
returns[TypeName *ast]:
|
returns[std::unique_ptr<TypeName> ast]:
|
||||||
IDENTIFIER {
|
IDENTIFIER {
|
||||||
auto text = $ctx->IDENTIFIER()->getText();
|
auto text = $ctx->IDENTIFIER()->getText();
|
||||||
$ast = new PrimitiveTypeName(getSourceRange($ctx), text);
|
auto named = std::make_unique<NamedTypeName>(getSourceRange($ctx), text);
|
||||||
|
$ast = ptrcast<TypeName>(named);
|
||||||
};
|
};
|
||||||
|
|
||||||
INT: [0-9]+ | '0x' [0-9a-fA-F]+ | '0o' [0-7]+ | '0b' [01]+;
|
INT: [0-9]+ | '0x' [0-9a-fA-F]+ | '0o' [0-7]+ | '0b' [01]+;
|
||||||
|
@ -57,8 +57,8 @@ ASTNode *ASTNode::fromJson(boost::json::value json) {
|
|||||||
if (type == "WhileStmt")
|
if (type == "WhileStmt")
|
||||||
return WhileStmt::fromJson(json);
|
return WhileStmt::fromJson(json);
|
||||||
|
|
||||||
if (type == "PrimitiveTypeName")
|
if (type == "NamedTypeName")
|
||||||
return PrimitiveTypeName::fromJson(json);
|
return NamedTypeName::fromJson(json);
|
||||||
|
|
||||||
throw std::runtime_error("json conversion for '" + type +
|
throw std::runtime_error("json conversion for '" + type +
|
||||||
"' not implemented");
|
"' not implemented");
|
||||||
|
@ -18,7 +18,7 @@ static const std::unordered_map<std::string, BinOp> stringToBinOp = {
|
|||||||
{"||", BinOp::OR},
|
{"||", BinOp::OR},
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::json::value BinExpr::toJson() {
|
boost::json::value BinExpr::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "BinExpr"},
|
{"@type", "BinExpr"},
|
||||||
{"op", binOpToString.at(op)},
|
{"op", binOpToString.at(op)},
|
||||||
@ -34,7 +34,7 @@ BinExpr *BinExpr::fromJson(boost::json::value json) {
|
|||||||
auto lhs = fromJsonProperty<BinExpr, Expr>(json, "lhs");
|
auto lhs = fromJsonProperty<BinExpr, Expr>(json, "lhs");
|
||||||
auto rhs = fromJsonProperty<BinExpr, Expr>(json, "rhs");
|
auto rhs = fromJsonProperty<BinExpr, Expr>(json, "rhs");
|
||||||
|
|
||||||
return new BinExpr(SourceRange::json(), op, lhs, rhs);
|
return new BinExpr(SourceRange::json(), op, std::move(lhs), std::move(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value CallExpr::toJson() {
|
boost::json::value CallExpr::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "CallExpr"},
|
{"@type", "CallExpr"},
|
||||||
{"callee", callee->toJson()},
|
{"callee", callee->toJson()},
|
||||||
@ -15,7 +15,7 @@ boost::json::value CallExpr::toJson() {
|
|||||||
CallExpr *CallExpr::fromJson(boost::json::value json) {
|
CallExpr *CallExpr::fromJson(boost::json::value json) {
|
||||||
auto callee = fromJsonProperty<CallExpr, Expr>(json, "callee");
|
auto callee = fromJsonProperty<CallExpr, Expr>(json, "callee");
|
||||||
auto args = fromJsonVector<CallExpr, Expr>(json, "args");
|
auto args = fromJsonVector<CallExpr, Expr>(json, "args");
|
||||||
return new CallExpr(SourceRange::json(), callee, args);
|
return new CallExpr(SourceRange::json(), std::move(callee), std::move(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value CastExpr::toJson() {
|
boost::json::value CastExpr::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "CastExpr"},
|
{"@type", "CastExpr"},
|
||||||
{"value", value->toJson()},
|
{"value", value->toJson()},
|
||||||
@ -15,7 +15,8 @@ boost::json::value CastExpr::toJson() {
|
|||||||
CastExpr *CastExpr::fromJson(boost::json::value json) {
|
CastExpr *CastExpr::fromJson(boost::json::value json) {
|
||||||
auto value = fromJsonProperty<CastExpr, Expr>(json, "value");
|
auto value = fromJsonProperty<CastExpr, Expr>(json, "value");
|
||||||
auto typeName = fromJsonProperty<CastExpr, TypeName>(json, "typeName");
|
auto typeName = fromJsonProperty<CastExpr, TypeName>(json, "typeName");
|
||||||
return new CastExpr(SourceRange::json(), value, typeName);
|
return new CastExpr(SourceRange::json(), std::move(value),
|
||||||
|
std::move(typeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value Identifier::toJson() {
|
boost::json::value Identifier::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "Identifier"},
|
{"@type", "Identifier"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
|
@ -4,18 +4,22 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value LambdaExpr::toJson() {
|
boost::json::value LambdaExpr::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "LambdaExpr"},
|
{"@type", "LambdaExpr"},
|
||||||
{"params", utils::mapToJson(params)},
|
{"params", utils::mapToJson(params)},
|
||||||
{"body", utils::mapToJson(body)},
|
{"returnTypeName", returnTypeName->toJson()},
|
||||||
|
{"body", body->toJson()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
LambdaExpr *LambdaExpr::fromJson(boost::json::value json) {
|
LambdaExpr *LambdaExpr::fromJson(boost::json::value json) {
|
||||||
auto params = fromJsonVector<LambdaExpr, FnParam>(json, "params");
|
auto params = fromJsonVector<LambdaExpr, FnParam>(json, "params");
|
||||||
auto body = fromJsonVector<LambdaExpr, Expr>(json, "body");
|
auto returnTypeName =
|
||||||
return new LambdaExpr(SourceRange::json(), params, body);
|
fromJsonProperty<LambdaExpr, TypeName>(json, "returnTypeName");
|
||||||
|
auto body = fromJsonProperty<LambdaExpr, Block>(json, "body");
|
||||||
|
return new LambdaExpr(SourceRange::json(), std::move(params),
|
||||||
|
std::move(returnTypeName), std::move(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -16,7 +16,7 @@ static const std::unordered_map<std::string, UnOp> stringToUnOp = {
|
|||||||
{"!", UnOp::NOT},
|
{"!", UnOp::NOT},
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::json::value UnExpr::toJson() {
|
boost::json::value UnExpr::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "UnExpr"},
|
{"@type", "UnExpr"},
|
||||||
{"op", unOpToString.at(op)},
|
{"op", unOpToString.at(op)},
|
||||||
@ -29,7 +29,7 @@ UnExpr *UnExpr::fromJson(boost::json::value json) {
|
|||||||
auto op = stringToUnOp.at(opString);
|
auto op = stringToUnOp.at(opString);
|
||||||
|
|
||||||
auto expr = fromJsonProperty<UnExpr, Expr>(json, "expr");
|
auto expr = fromJsonProperty<UnExpr, Expr>(json, "expr");
|
||||||
return new UnExpr(SourceRange::json(), op, expr);
|
return new UnExpr(SourceRange::json(), op, std::move(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
// boost::json::value NullValue::toJson() { return nullptr; }
|
// boost::json::value NullValue::toJson() const { return nullptr; }
|
||||||
|
|
||||||
// std::unique_ptr<NullValue>
|
// std::unique_ptr<NullValue>
|
||||||
// NullValue::fromJson(boost::json::value json) {
|
// NullValue::fromJson(boost::json::value json) {
|
||||||
// return std::make_unique<NullValue>(SourceRange::json());
|
// return std::make_unique<NullValue>(SourceRange::json());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
boost::json::value IntValue::toJson() { return value; }
|
boost::json::value IntValue::toJson() const { return value; }
|
||||||
|
|
||||||
IntValue *IntValue::fromJson(boost::json::value json) {
|
IntValue *IntValue::fromJson(boost::json::value json) {
|
||||||
return new IntValue(SourceRange::json(), json.as_int64());
|
return new IntValue(SourceRange::json(), json.as_int64());
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::json::value FloatValue::toJson() { return value; }
|
boost::json::value FloatValue::toJson() const { return value; }
|
||||||
|
|
||||||
FloatValue *FloatValue::fromJson(boost::json::value json) {
|
FloatValue *FloatValue::fromJson(boost::json::value json) {
|
||||||
return new FloatValue(SourceRange::json(), json.as_double());
|
return new FloatValue(SourceRange::json(), json.as_double());
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value Import::toJson() {
|
boost::json::value Import::toJson() const {
|
||||||
return {{"@type", "Import"}, {"moduleName", moduleName}};
|
return {{"@type", "Import"}, {"moduleName", moduleName}};
|
||||||
}
|
}
|
||||||
Import *Import::fromJson(boost::json::value json) {
|
Import *Import::fromJson(boost::json::value json) {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value Module::toJson() {
|
boost::json::value Module::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "Module"},
|
{"@type", "Module"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
@ -18,7 +18,8 @@ Module *Module::fromJson(boost::json::value json) {
|
|||||||
auto imports = fromJsonVector<Module, Import>(json, "imports");
|
auto imports = fromJsonVector<Module, Import>(json, "imports");
|
||||||
auto stmts = fromJsonVector<Module, Stmt>(json, "stmts");
|
auto stmts = fromJsonVector<Module, Stmt>(json, "stmts");
|
||||||
|
|
||||||
return new Module(SourceRange::json(), name, imports, stmts);
|
return new Module(SourceRange::json(), name, std::move(imports),
|
||||||
|
std::move(stmts));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value AssignStmt::toJson() {
|
boost::json::value AssignStmt::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "AssignStmt"},
|
{"@type", "AssignStmt"},
|
||||||
{"lval", lval->toJson()},
|
{"lval", lval->toJson()},
|
||||||
@ -14,7 +14,7 @@ boost::json::value AssignStmt::toJson() {
|
|||||||
AssignStmt *AssignStmt::fromJson(boost::json::value json) {
|
AssignStmt *AssignStmt::fromJson(boost::json::value json) {
|
||||||
auto lval = fromJsonProperty<AssignStmt, Expr>(json, "lval");
|
auto lval = fromJsonProperty<AssignStmt, Expr>(json, "lval");
|
||||||
auto rval = fromJsonProperty<AssignStmt, Expr>(json, "rval");
|
auto rval = fromJsonProperty<AssignStmt, Expr>(json, "rval");
|
||||||
return new AssignStmt(SourceRange::json(), lval, rval);
|
return new AssignStmt(SourceRange::json(), std::move(lval), std::move(rval));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
20
compiler/src/AST/Stmt/Block.cpp
Normal file
20
compiler/src/AST/Stmt/Block.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "AST/AST.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
namespace plsm {
|
||||||
|
namespace ast {
|
||||||
|
|
||||||
|
boost::json::value Block::toJson() const {
|
||||||
|
return {
|
||||||
|
{"@type", "Block"},
|
||||||
|
{"stmts", utils::mapToJson(stmts)},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Block *Block::fromJson(boost::json::value json) {
|
||||||
|
auto stmts = fromJsonVector<Block, Stmt>(json, "stmts");
|
||||||
|
return new Block(SourceRange::json(), std::move(stmts));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ast
|
||||||
|
} // namespace plsm
|
@ -3,7 +3,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value ExprStmt::toJson() {
|
boost::json::value ExprStmt::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "ExprStmt"},
|
{"@type", "ExprStmt"},
|
||||||
{"expr", expr->toJson()},
|
{"expr", expr->toJson()},
|
||||||
@ -12,7 +12,7 @@ boost::json::value ExprStmt::toJson() {
|
|||||||
|
|
||||||
ExprStmt *ExprStmt::fromJson(boost::json::value json) {
|
ExprStmt *ExprStmt::fromJson(boost::json::value json) {
|
||||||
auto expr = fromJsonProperty<ExprStmt, Expr>(json, "expr");
|
auto expr = fromJsonProperty<ExprStmt, Expr>(json, "expr");
|
||||||
return new ExprStmt(SourceRange::json(), expr);
|
return new ExprStmt(SourceRange::json(), std::move(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value FnParam::toJson() {
|
boost::json::value FnParam::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "FnParam"},
|
{"@type", "FnParam"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
@ -15,16 +15,16 @@ boost::json::value FnParam::toJson() {
|
|||||||
FnParam *FnParam::fromJson(boost::json::value json) {
|
FnParam *FnParam::fromJson(boost::json::value json) {
|
||||||
auto name = getJsonValue<FnParam, std::string>(json, "name");
|
auto name = getJsonValue<FnParam, std::string>(json, "name");
|
||||||
auto typeName = fromJsonProperty<FnParam, TypeName>(json, "typeName");
|
auto typeName = fromJsonProperty<FnParam, TypeName>(json, "typeName");
|
||||||
return new FnParam(SourceRange::json(), name, typeName);
|
return new FnParam(SourceRange::json(), name, std::move(typeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::json::value FnDecl::toJson() {
|
boost::json::value FnDecl::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "FnDecl"},
|
{"@type", "FnDecl"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
{"params", utils::mapToJson(params)},
|
{"params", utils::mapToJson(params)},
|
||||||
{"returnTypeName", returnTypeName->toJson()},
|
{"returnTypeName", returnTypeName->toJson()},
|
||||||
{"body", utils::mapToJson(body)},
|
{"body", body->toJson()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,8 +33,9 @@ FnDecl *FnDecl::fromJson(boost::json::value json) {
|
|||||||
auto params = fromJsonVector<FnDecl, FnParam>(json, "params");
|
auto params = fromJsonVector<FnDecl, FnParam>(json, "params");
|
||||||
auto returnTypeName =
|
auto returnTypeName =
|
||||||
fromJsonProperty<FnDecl, TypeName>(json, "returnTypeName");
|
fromJsonProperty<FnDecl, TypeName>(json, "returnTypeName");
|
||||||
auto body = fromJsonVector<FnDecl, Stmt>(json, "body");
|
auto body = fromJsonProperty<FnDecl, Block>(json, "body");
|
||||||
return new FnDecl(SourceRange::json(), name, params, returnTypeName, body);
|
return new FnDecl(SourceRange::json(), name, std::move(params),
|
||||||
|
std::move(returnTypeName), std::move(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -4,20 +4,21 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value IfStmt::toJson() {
|
boost::json::value IfStmt::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "IfStmt"},
|
{"@type", "IfStmt"},
|
||||||
{"condition", condition->toJson()},
|
{"condition", condition->toJson()},
|
||||||
{"ifBody", utils::mapToJson(ifBody)},
|
{"ifBody", ifBody->toJson()},
|
||||||
{"elseBody", utils::mapToJson(elseBody)},
|
{"elseBody", elseBody->toJson()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
IfStmt *IfStmt::fromJson(boost::json::value json) {
|
IfStmt *IfStmt::fromJson(boost::json::value json) {
|
||||||
auto condition = fromJsonProperty<IfStmt, Expr>(json, "condition");
|
auto condition = fromJsonProperty<IfStmt, Expr>(json, "condition");
|
||||||
auto ifBody = fromJsonVector<IfStmt, Stmt>(json, "ifBody");
|
auto ifBody = fromJsonProperty<IfStmt, Block>(json, "ifBody");
|
||||||
auto elseBody = fromJsonVector<IfStmt, Stmt>(json, "elseBody");
|
auto elseBody = fromJsonProperty<IfStmt, Block>(json, "elseBody");
|
||||||
return new IfStmt(SourceRange::json(), condition, ifBody, elseBody);
|
return new IfStmt(SourceRange::json(), std::move(condition),
|
||||||
|
std::move(ifBody), std::move(elseBody));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value RetStmt::toJson() {
|
boost::json::value RetStmt::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "RetStmt"},
|
{"@type", "RetStmt"},
|
||||||
{"value", value->toJson()},
|
{"value", value->toJson()},
|
||||||
@ -12,7 +12,7 @@ boost::json::value RetStmt::toJson() {
|
|||||||
|
|
||||||
RetStmt *RetStmt::fromJson(boost::json::value json) {
|
RetStmt *RetStmt::fromJson(boost::json::value json) {
|
||||||
auto value = fromJsonProperty<RetStmt, Expr>(json, "value");
|
auto value = fromJsonProperty<RetStmt, Expr>(json, "value");
|
||||||
return new RetStmt(SourceRange::json(), value);
|
return new RetStmt(SourceRange::json(), std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value VarDecl::toJson() {
|
boost::json::value VarDecl::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "VarDecl"},
|
{"@type", "VarDecl"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
@ -14,7 +14,7 @@ boost::json::value VarDecl::toJson() {
|
|||||||
VarDecl *VarDecl::fromJson(boost::json::value json) {
|
VarDecl *VarDecl::fromJson(boost::json::value json) {
|
||||||
auto name = getJsonValue<VarDecl, std::string>(json, "name");
|
auto name = getJsonValue<VarDecl, std::string>(json, "name");
|
||||||
auto typeName = fromJsonProperty<VarDecl, TypeName>(json, "typeName");
|
auto typeName = fromJsonProperty<VarDecl, TypeName>(json, "typeName");
|
||||||
return new VarDecl(SourceRange::json(), name, typeName);
|
return new VarDecl(SourceRange::json(), name, std::move(typeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -4,18 +4,19 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value WhileStmt::toJson() {
|
boost::json::value WhileStmt::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "WhileStmt"},
|
{"@type", "WhileStmt"},
|
||||||
{"condition", condition->toJson()},
|
{"condition", condition->toJson()},
|
||||||
{"body", utils::mapToJson(body)},
|
{"body", body->toJson()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
WhileStmt *WhileStmt::fromJson(boost::json::value json) {
|
WhileStmt *WhileStmt::fromJson(boost::json::value json) {
|
||||||
auto condition = fromJsonProperty<WhileStmt, Expr>(json, "condition");
|
auto condition = fromJsonProperty<WhileStmt, Expr>(json, "condition");
|
||||||
auto body = fromJsonVector<WhileStmt, Stmt>(json, "body");
|
auto body = fromJsonProperty<WhileStmt, Block>(json, "body");
|
||||||
return new WhileStmt(SourceRange::json(), condition, body);
|
return new WhileStmt(SourceRange::json(), std::move(condition),
|
||||||
|
std::move(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
#include "AST/Type/FunctionType.h"
|
||||||
#include "AST/AST.h"
|
#include "AST/AST.h"
|
||||||
|
#include "AST/Base.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value FunctionType::toJson() {
|
boost::json::value FunctionType::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "FunctionType"},
|
{"@type", "FunctionType"},
|
||||||
{"paramTypes", utils::mapToJson(paramTypes)},
|
{"paramTypes", utils::mapToJson(paramTypes)},
|
||||||
@ -13,10 +16,19 @@ boost::json::value FunctionType::toJson() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FunctionType *FunctionType::fromJson(boost::json::value json) {
|
FunctionType *FunctionType::fromJson(boost::json::value json) {
|
||||||
auto paramTypes = fromJsonVector<FunctionType, Type>(json, "paramTypes");
|
auto paramTypesU = fromJsonVector<FunctionType, Type>(json, "paramTypes");
|
||||||
auto returnType = fromJsonProperty<FunctionType, Type>(json, "returnType");
|
auto returnTypeU = fromJsonProperty<FunctionType, Type>(json, "returnType");
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Type>> paramTypes;
|
||||||
|
for (auto ¶mType : paramTypesU)
|
||||||
|
paramTypes.push_back(std::shared_ptr<Type>(paramType.release()));
|
||||||
|
|
||||||
|
auto returnType = std::shared_ptr<Type>(returnTypeU.release());
|
||||||
|
|
||||||
return new FunctionType(paramTypes, returnType);
|
return new FunctionType(paramTypes, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeName *FunctionType::toTypeName() { return nullptr; }
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace plsm
|
} // namespace plsm
|
@ -1,9 +1,12 @@
|
|||||||
#include "AST/AST.h"
|
#include "AST/AST.h"
|
||||||
|
#include "AST/Base.h"
|
||||||
|
#include "AST/TypeName/NamedTypeName.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value PrimitiveType::toJson() {
|
boost::json::value PrimitiveType::toJson() const {
|
||||||
return {
|
return {
|
||||||
{"@type", "PrimitiveType"},
|
{"@type", "PrimitiveType"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
@ -15,5 +18,9 @@ PrimitiveType *PrimitiveType::fromJson(boost::json::value json) {
|
|||||||
return new PrimitiveType(name);
|
return new PrimitiveType(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeName *PrimitiveType::toTypeName() {
|
||||||
|
return new NamedTypeName(SourceRange::unknown(), name);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace plsm
|
} // namespace plsm
|
@ -3,13 +3,13 @@
|
|||||||
namespace plsm {
|
namespace plsm {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
boost::json::value PrimitiveTypeName::toJson() {
|
boost::json::value NamedTypeName::toJson() const {
|
||||||
return {{"@type", "PrimitiveTypeName"}, {"name", name}};
|
return {{"@type", "NamedTypeName"}, {"name", name}};
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimitiveTypeName *PrimitiveTypeName::fromJson(boost::json::value json) {
|
NamedTypeName *NamedTypeName::fromJson(boost::json::value json) {
|
||||||
auto name = getJsonValue<PrimitiveTypeName, std::string>(json, "name");
|
auto name = getJsonValue<NamedTypeName, std::string>(json, "name");
|
||||||
return new PrimitiveTypeName(SourceRange::json(), name);
|
return new NamedTypeName(SourceRange::json(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
@ -1,58 +1,138 @@
|
|||||||
#include "AST/BaseASTVisitor.h"
|
#include "AST/BaseASTVisitor.h"
|
||||||
#include "Analysis.h"
|
#include "Analysis.h"
|
||||||
|
#include "Errors.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
#include <vector>
|
||||||
|
|
||||||
namespace plsm {
|
namespace plsm {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class NameAnalysisVisitor1 : public ast::BaseASTVisitor {
|
class NameAnalysisVisitor1 : public ast::BaseASTVisitor {
|
||||||
std::stack<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes;
|
std::vector<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NameAnalysisVisitor1(
|
NameAnalysisVisitor1(
|
||||||
std::stack<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes)
|
std::vector<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes)
|
||||||
: scopes(scopes) {}
|
: scopes(scopes) {}
|
||||||
|
|
||||||
virtual std::any visit(ast::FnDecl &fnDecl, std::any param) override {
|
virtual std::any visit(ast::FnDecl &fnDecl, std::any param) override {
|
||||||
|
if (!fnDecl.name.size())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
auto symbol = std::make_shared<ast::Symbol>(fnDecl.name);
|
auto symbol = std::make_shared<ast::Symbol>(fnDecl.name);
|
||||||
fnDecl.symbol = symbol;
|
fnDecl.symbol = symbol;
|
||||||
scopes->top()[fnDecl.name] = symbol;
|
scopes->back()[fnDecl.name] = symbol;
|
||||||
|
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::any visit(ast::VarDecl &varDecl, std::any param) override {
|
virtual std::any visit(ast::VarDecl &varDecl, std::any param) override {
|
||||||
|
if (!varDecl.name.size())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
auto symbol = std::make_shared<ast::Symbol>(varDecl.name);
|
auto symbol = std::make_shared<ast::Symbol>(varDecl.name);
|
||||||
varDecl.symbol = symbol;
|
varDecl.symbol = symbol;
|
||||||
scopes->top()[varDecl.name] = symbol;
|
scopes->back()[varDecl.name] = symbol;
|
||||||
|
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NameAnalysisVisitor2 : public ast::BaseASTVisitor {
|
class NameAnalysisVisitor2 : public ast::BaseASTVisitor {
|
||||||
std::stack<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes;
|
std::vector<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes;
|
||||||
|
|
||||||
void push() {
|
void push() {
|
||||||
scopes->push(std::map<std::string, std::shared_ptr<ast::Symbol>>());
|
scopes->push_back(std::map<std::string, std::shared_ptr<ast::Symbol>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop() { scopes->pop(); }
|
void pop() { scopes->pop_back(); }
|
||||||
|
|
||||||
|
std::shared_ptr<ast::Symbol> findSymbol(std::string name) {
|
||||||
|
for (long i = scopes->size() - 1; i >= 0; i--) {
|
||||||
|
auto scope = scopes->at(i);
|
||||||
|
if (scope.count(name))
|
||||||
|
return scope[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::shared_ptr<ast::Symbol>();
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NameAnalysisVisitor2(
|
NameAnalysisVisitor2(
|
||||||
std::stack<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes)
|
std::vector<std::map<std::string, std::shared_ptr<ast::Symbol>>> *scopes)
|
||||||
: scopes(scopes) {}
|
: scopes(scopes) {}
|
||||||
|
|
||||||
|
virtual std::any visit(ast::FnParam &fnParam, std::any param) override {
|
||||||
|
if (!fnParam.name.size())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
auto symbol = std::make_shared<ast::Symbol>(fnParam.name);
|
||||||
|
fnParam.symbol = symbol;
|
||||||
|
scopes->back()[fnParam.name] = symbol;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(ast::FnDecl &fnDecl, std::any param) override {
|
||||||
|
push();
|
||||||
|
BaseASTVisitor::visit(fnDecl, param);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(ast::Block &block, std::any param) override {
|
||||||
|
push();
|
||||||
|
BaseASTVisitor::visit(block, param);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(ast::LambdaExpr &lambdaExpr, std::any param) override {
|
||||||
|
push();
|
||||||
|
BaseASTVisitor::visit(lambdaExpr, param);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(ast::Identifier &identifier, std::any param) override {
|
||||||
|
if (!identifier.name.size())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
auto symbol = findSymbol(identifier.name);
|
||||||
|
|
||||||
|
if (!symbol.get()) {
|
||||||
|
errors::put(identifier.error("unable to resolve identifier '" +
|
||||||
|
identifier.name + "'"));
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
identifier.symbol = symbol;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(ast::VarDecl &varDecl, std::any param) override {
|
||||||
|
if (!varDecl.name.size())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
auto symbol = std::make_shared<ast::Symbol>(varDecl.name);
|
||||||
|
varDecl.symbol = symbol;
|
||||||
|
scopes->back()[varDecl.name] = symbol;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void performNameAnalysis(std::shared_ptr<ast::Module> module) {
|
void performNameAnalysis(std::unique_ptr<ast::Module> &module) {
|
||||||
std::stack<std::map<std::string, std::shared_ptr<ast::Symbol>>> scopes;
|
std::vector<std::map<std::string, std::shared_ptr<ast::Symbol>>> scopes;
|
||||||
scopes.push(std::map<std::string, std::shared_ptr<ast::Symbol>>());
|
scopes.push_back(std::map<std::string, std::shared_ptr<ast::Symbol>>());
|
||||||
|
|
||||||
NameAnalysisVisitor1 visitor1(&scopes);
|
NameAnalysisVisitor1 visitor1(&scopes);
|
||||||
NameAnalysisVisitor2 visitor2(&scopes);
|
NameAnalysisVisitor2 visitor2(&scopes);
|
||||||
@ -62,6 +142,7 @@ void performNameAnalysis(std::shared_ptr<ast::Module> module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &stmt : module->stmts) {
|
for (auto &stmt : module->stmts) {
|
||||||
|
if (utils::is<ast::FnDecl>(stmt.get()))
|
||||||
stmt->accept(&visitor2, nullptr);
|
stmt->accept(&visitor2, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
407
compiler/src/Anlaysis/TypeAnalysis.cpp
Normal file
407
compiler/src/Anlaysis/TypeAnalysis.cpp
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
#include "AST/Base.h"
|
||||||
|
#include "AST/Type/PrimitiveType.h"
|
||||||
|
#include "Analysis.h"
|
||||||
|
|
||||||
|
#include "AST/BaseASTVisitor.h"
|
||||||
|
#include "Errors.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace plsm {
|
||||||
|
|
||||||
|
using namespace ast;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static std::map<std::string, std::shared_ptr<PrimitiveType>> primitiveTypes = {
|
||||||
|
{"i8", std::make_shared<PrimitiveType>("i8")},
|
||||||
|
{"i16", std::make_shared<PrimitiveType>("i16")},
|
||||||
|
{"i32", std::make_shared<PrimitiveType>("i32")},
|
||||||
|
{"i64", std::make_shared<PrimitiveType>("i64")},
|
||||||
|
{"u8", std::make_shared<PrimitiveType>("u8")},
|
||||||
|
{"u16", std::make_shared<PrimitiveType>("u16")},
|
||||||
|
{"u32", std::make_shared<PrimitiveType>("u32")},
|
||||||
|
{"u64", std::make_shared<PrimitiveType>("u64")},
|
||||||
|
{"float", std::make_shared<PrimitiveType>("float")},
|
||||||
|
{"double", std::make_shared<PrimitiveType>("double")},
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::shared_ptr<Type> resolveTypeName(const TypeName *typeName) {
|
||||||
|
if (utils::is<NamedTypeName>(typeName)) {
|
||||||
|
auto named = (NamedTypeName *)typeName;
|
||||||
|
if (primitiveTypes.count(named->name))
|
||||||
|
return primitiveTypes[named->name];
|
||||||
|
|
||||||
|
errors::put(
|
||||||
|
typeName->error("unable to resolve named type '" + named->name + "'"));
|
||||||
|
return std::shared_ptr<Type>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: function type
|
||||||
|
|
||||||
|
errors::put(typeName->error("unable to resolve type"));
|
||||||
|
return std::shared_ptr<Type>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void castTo(std::unique_ptr<Expr> &expr,
|
||||||
|
const std::shared_ptr<Type> &type) {
|
||||||
|
auto cast = new CastExpr(expr->sourceRange, std::move(expr),
|
||||||
|
std::unique_ptr<TypeName>(type->toTypeName()));
|
||||||
|
cast->type = type;
|
||||||
|
cast->typeName->type = type;
|
||||||
|
|
||||||
|
auto newExpr = std::unique_ptr<Expr>(cast);
|
||||||
|
expr.swap(newExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tryAssignTo(std::unique_ptr<Expr> &from,
|
||||||
|
const std::shared_ptr<Type> &toType) {
|
||||||
|
if (*from->type == *toType)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (utils::is<PrimitiveType>(from->type.get()) &&
|
||||||
|
utils::is<PrimitiveType>(toType.get())) {
|
||||||
|
PrimitiveType *fromT = (PrimitiveType *)from->type.get();
|
||||||
|
const PrimitiveType *toT = (PrimitiveType *)toType.get();
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<std::string>> castMatrix = {
|
||||||
|
{"i8", {"i16", "i32", "i64", "u8", "u16", "u32", "u64"}},
|
||||||
|
{"i16", {"i32", "i64", "u16", "u32", "u64"}},
|
||||||
|
{"i32", {"i64", "u32", "u64"}},
|
||||||
|
{"i64", {"u64"}},
|
||||||
|
{"u8", {"i16", "i32", "i64", "u16", "u32", "u64"}},
|
||||||
|
{"u16", {"i32", "i64", "u32", "u64"}},
|
||||||
|
{"u32", {"i64", "u64"}},
|
||||||
|
{"u64", {}},
|
||||||
|
{"float", {"double"}},
|
||||||
|
{"double", {}},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!castMatrix.count(fromT->name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto castableTo = castMatrix[fromT->name];
|
||||||
|
|
||||||
|
for (auto &toName : castableTo) {
|
||||||
|
if (toT->name == toName) {
|
||||||
|
castTo(from, toType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool canBeCastedTo(std::unique_ptr<Expr> &from,
|
||||||
|
const std::shared_ptr<Type> &toType) {
|
||||||
|
if (*from->type == *toType)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (utils::is<PrimitiveType>(from->type.get()) &&
|
||||||
|
utils::is<PrimitiveType>(toType.get())) {
|
||||||
|
PrimitiveType *fromT = (PrimitiveType *)from->type.get();
|
||||||
|
const PrimitiveType *toT = (PrimitiveType *)toType.get();
|
||||||
|
|
||||||
|
std::vector<std::string> allNumberTypes = {"i8", "i16", "i32", "i64",
|
||||||
|
"u8", "u16", "u32", "u64",
|
||||||
|
"float", "double"};
|
||||||
|
std::map<std::string, std::vector<std::string>> castMatrix = {
|
||||||
|
{"i8", allNumberTypes}, {"i16", allNumberTypes},
|
||||||
|
{"i32", allNumberTypes}, {"i64", allNumberTypes},
|
||||||
|
{"u8", allNumberTypes}, {"u16", allNumberTypes},
|
||||||
|
{"u32", allNumberTypes}, {"u64", allNumberTypes},
|
||||||
|
{"float", allNumberTypes}, {"double", allNumberTypes},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!castMatrix.count(fromT->name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto castableTo = castMatrix[fromT->name];
|
||||||
|
|
||||||
|
for (auto &toName : castableTo) {
|
||||||
|
if (toT->name == toName) {
|
||||||
|
castTo(from, toType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeAnalysisVisitor1 : public BaseASTVisitor {
|
||||||
|
public:
|
||||||
|
virtual std::any visit(NamedTypeName &namedTypeName,
|
||||||
|
std::any param) override {
|
||||||
|
namedTypeName.type = resolveTypeName(&namedTypeName);
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(VarDecl &varDecl, std::any param) override {
|
||||||
|
if (!varDecl.typeName.get() || !varDecl.symbol.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
varDecl.typeName->accept(this, param);
|
||||||
|
if (varDecl.typeName->type.get())
|
||||||
|
varDecl.symbol->type = varDecl.typeName->type;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(FnParam &fnParam, std::any param) override {
|
||||||
|
if (!fnParam.typeName.get() || !fnParam.symbol.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
fnParam.typeName->accept(this, param);
|
||||||
|
if (fnParam.typeName->type.get())
|
||||||
|
fnParam.symbol->type = fnParam.typeName->type;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(FnDecl &fnDecl, std::any param) override {
|
||||||
|
if (!fnDecl.symbol.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
std::shared_ptr<Type> returnType(nullptr);
|
||||||
|
if (fnDecl.returnTypeName.get()) {
|
||||||
|
fnDecl.returnTypeName->accept(this, param);
|
||||||
|
returnType = fnDecl.returnTypeName->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Type>> paramTypes;
|
||||||
|
for (auto &p : fnDecl.params) {
|
||||||
|
if (p.get())
|
||||||
|
p->accept(this, param);
|
||||||
|
|
||||||
|
if (p->symbol.get()) {
|
||||||
|
paramTypes.push_back(p->symbol->type);
|
||||||
|
} else {
|
||||||
|
paramTypes.push_back(std::shared_ptr<Type>(nullptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fnDecl.symbol->type =
|
||||||
|
std::make_shared<FunctionType>(paramTypes, returnType);
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TypeAnalysisVisitor2 : public BaseASTVisitor {
|
||||||
|
std::shared_ptr<Type> currentReturnType = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual std::any visit(NamedTypeName &namedTypeName,
|
||||||
|
std::any param) override {
|
||||||
|
namedTypeName.type = resolveTypeName(&namedTypeName);
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(VarDecl &varDecl, std::any param) override {
|
||||||
|
if (!varDecl.typeName.get() || !varDecl.symbol.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
varDecl.typeName->accept(this, param);
|
||||||
|
if (varDecl.typeName->type.get())
|
||||||
|
varDecl.symbol->type = varDecl.typeName->type;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(FnParam &fnParam, std::any param) override {
|
||||||
|
if (!fnParam.typeName.get() || !fnParam.symbol.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
fnParam.typeName->accept(this, param);
|
||||||
|
fnParam.symbol->type = resolveTypeName(fnParam.typeName.get());
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(FnDecl &fnDecl, std::any param) override {
|
||||||
|
if (fnDecl.symbol.get() && fnDecl.symbol->type.get()) {
|
||||||
|
auto functionType = (FunctionType *)fnDecl.symbol->type.get();
|
||||||
|
currentReturnType = functionType->returnType;
|
||||||
|
} else {
|
||||||
|
currentReturnType = std::shared_ptr<Type>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fnDecl.body.get())
|
||||||
|
fnDecl.body->accept(this, param);
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(Identifier &identifier, std::any param) override {
|
||||||
|
if (!identifier.symbol.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
identifier.type = identifier.symbol->type;
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(IntValue &intValue, std::any param) override {
|
||||||
|
if ((int8_t)intValue.value == intValue.value) {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("i8");
|
||||||
|
} else if ((uint8_t)intValue.value == intValue.value) {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("u8");
|
||||||
|
} else if ((int16_t)intValue.value == intValue.value) {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("i16");
|
||||||
|
} else if ((uint16_t)intValue.value == intValue.value) {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("u16");
|
||||||
|
} else if ((int32_t)intValue.value == intValue.value) {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("i32");
|
||||||
|
} else if ((uint32_t)intValue.value == intValue.value) {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("u32");
|
||||||
|
} else {
|
||||||
|
intValue.type = std::make_shared<PrimitiveType>("i64");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(FloatValue &floatValue, std::any param) override {
|
||||||
|
if ((float_t)floatValue.value == floatValue.value) {
|
||||||
|
floatValue.type = std::make_shared<PrimitiveType>("float");
|
||||||
|
} else {
|
||||||
|
floatValue.type = std::make_shared<PrimitiveType>("double");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(CastExpr &castExpr, std::any param) override {
|
||||||
|
BaseASTVisitor::visit(castExpr, param);
|
||||||
|
|
||||||
|
// do not multiplicate errors
|
||||||
|
if (!castExpr.value.get() || !castExpr.value->type.get())
|
||||||
|
return std::any();
|
||||||
|
if (!castExpr.typeName.get() || !castExpr.typeName->type.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
if (!canBeCastedTo(castExpr.value, castExpr.typeName->type)) {
|
||||||
|
errors::put(castExpr.error("cast type mismatch"));
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
castExpr.type = castExpr.typeName->type;
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(AssignStmt &assignStmt, std::any param) override {
|
||||||
|
BaseASTVisitor::visit(assignStmt, param);
|
||||||
|
|
||||||
|
// do not multiplicate errors
|
||||||
|
if (!assignStmt.lval.get() || !assignStmt.lval->type.get())
|
||||||
|
return std::any();
|
||||||
|
if (!assignStmt.lval.get() || !assignStmt.rval->type.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
if (!tryAssignTo(assignStmt.rval, assignStmt.lval->type)) {
|
||||||
|
errors::put(assignStmt.error("assignment type mismatch"));
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(RetStmt &retStmt, std::any param) override {
|
||||||
|
BaseASTVisitor::visit(retStmt, param);
|
||||||
|
|
||||||
|
// do not multiplicate errors
|
||||||
|
if (!retStmt.value.get() || !retStmt.value->type.get())
|
||||||
|
return std::any();
|
||||||
|
if (!currentReturnType.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
if (!tryAssignTo(retStmt.value, currentReturnType)) {
|
||||||
|
errors::put(retStmt.error("return type mismatch"));
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(IfStmt &ifStmt, std::any param) override {
|
||||||
|
BaseASTVisitor::visit(ifStmt, param);
|
||||||
|
|
||||||
|
// do not multiplicate errors
|
||||||
|
if (ifStmt.condition.get() && ifStmt.condition->type.get()) {
|
||||||
|
if (!utils::is<PrimitiveType>(ifStmt.condition->type.get())) {
|
||||||
|
errors::put(ifStmt.error("condition must be of primitive type"));
|
||||||
|
} else {
|
||||||
|
// cast condition to int (to make sure jnz succeeds)
|
||||||
|
castTo(ifStmt.condition, std::make_shared<PrimitiveType>("i32"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(WhileStmt &whileStmt, std::any param) override {
|
||||||
|
BaseASTVisitor::visit(whileStmt, param);
|
||||||
|
|
||||||
|
// do not multiplicate errors
|
||||||
|
if (whileStmt.condition.get() && whileStmt.condition->type.get()) {
|
||||||
|
if (!utils::is<PrimitiveType>(whileStmt.condition->type.get())) {
|
||||||
|
errors::put(whileStmt.error("condition must be of primitive type"));
|
||||||
|
return std::any();
|
||||||
|
} else {
|
||||||
|
// cast condition to int (to make sure jnz succeeds)
|
||||||
|
castTo(whileStmt.condition, std::make_shared<PrimitiveType>("i32"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::any visit(CallExpr &callExpr, std::any param) override {
|
||||||
|
BaseASTVisitor::visit(callExpr, param);
|
||||||
|
|
||||||
|
// do not multiplicate errors
|
||||||
|
if (!callExpr.callee.get() || !callExpr.callee->type.get())
|
||||||
|
return std::any();
|
||||||
|
|
||||||
|
if (!utils::is<FunctionType>(callExpr.callee->type.get())) {
|
||||||
|
errors::put(callExpr.error("callee must be a function"));
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
callExpr.type = callExpr.callee->type;
|
||||||
|
|
||||||
|
auto functionType = (FunctionType *)(callExpr.callee->type.get());
|
||||||
|
if (functionType->paramTypes.size() != callExpr.args.size()) {
|
||||||
|
errors::put(callExpr.error("wrong number of arguments"));
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void performTypeAnalysis(std::unique_ptr<Module> &module) {
|
||||||
|
TypeAnalysisVisitor1 visitor1;
|
||||||
|
TypeAnalysisVisitor2 visitor2;
|
||||||
|
|
||||||
|
for (auto &stmt : module->stmts) {
|
||||||
|
stmt->accept(&visitor1, std::any());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &stmt : module->stmts) {
|
||||||
|
if (utils::is<FnDecl>(stmt.get()))
|
||||||
|
stmt->accept(&visitor2, std::any());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace plsm
|
7
compiler/src/Errors.cpp
Normal file
7
compiler/src/Errors.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "Errors.h"
|
||||||
|
|
||||||
|
static std::vector<std::string> _errors;
|
||||||
|
|
||||||
|
void plsm::errors::put(const std::string &error) { _errors.push_back(error); }
|
||||||
|
|
||||||
|
std::vector<std::string> plsm::errors::get() { return std::vector(_errors); }
|
@ -1,46 +1,49 @@
|
|||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
|
|
||||||
#include "AST/AST.h"
|
#include "AST/AST.h"
|
||||||
|
#include "Errors.h"
|
||||||
#include "plsmBaseVisitor.h"
|
#include "plsmBaseVisitor.h"
|
||||||
#include "plsmLexer.h"
|
#include "plsmLexer.h"
|
||||||
#include "plsmParser.h"
|
#include "plsmParser.h"
|
||||||
|
|
||||||
|
namespace plsm {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class MyAntlr4ErrorListener : public antlr4::BaseErrorListener {
|
class MyAntlr4ErrorListener : public antlr4::BaseErrorListener {
|
||||||
std::string file;
|
std::string file;
|
||||||
std::string *error;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyAntlr4ErrorListener(const std::string &file, std::string *error)
|
MyAntlr4ErrorListener(const std::string &file) : file(file) {}
|
||||||
: file(file), error(error) {}
|
|
||||||
|
|
||||||
virtual void syntaxError(antlr4::Recognizer *recognizer,
|
virtual void syntaxError(antlr4::Recognizer *recognizer,
|
||||||
antlr4::Token *offendingSymbol, size_t line,
|
antlr4::Token *offendingSymbol, size_t line,
|
||||||
size_t charPositionInLine, const std::string &msg,
|
size_t charPositionInLine, const std::string &msg,
|
||||||
std::exception_ptr e) override {
|
std::exception_ptr e) override {
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << file << ": line " << line << ":" << charPositionInLine << ": " << msg;
|
ss << "In file " << file << ":" << line << ":" << charPositionInLine << "\n"
|
||||||
*error = ss.str();
|
<< terminal::red << msg << terminal::reset;
|
||||||
|
|
||||||
|
errors::put(ss.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace plsm {
|
std::unique_ptr<ast::Module> parse(const std::string &file,
|
||||||
|
|
||||||
std::shared_ptr<ast::Module> parse(const std::string &file,
|
|
||||||
const std::string &input) {
|
const std::string &input) {
|
||||||
auto istream = antlr4::ANTLRInputStream(input);
|
auto istream = antlr4::ANTLRInputStream(input);
|
||||||
auto lexer = plsmLexer(&istream);
|
auto lexer = plsmLexer(&istream);
|
||||||
auto tokens = antlr4::CommonTokenStream(&lexer);
|
auto tokens = antlr4::CommonTokenStream(&lexer);
|
||||||
auto parser = plsmParser(&tokens);
|
auto parser = plsmParser(&tokens);
|
||||||
|
parser.setFileName(file);
|
||||||
|
parser.setSourceText(input);
|
||||||
|
|
||||||
std::string error;
|
MyAntlr4ErrorListener listener(file);
|
||||||
MyAntlr4ErrorListener listener(file, &error);
|
|
||||||
parser.removeErrorListeners();
|
parser.removeErrorListeners();
|
||||||
parser.addErrorListener(&listener);
|
parser.addErrorListener(&listener);
|
||||||
|
|
||||||
auto tree = parser.module();
|
auto tree = parser.module();
|
||||||
return std::shared_ptr<Module>(tree->ast);
|
return std::move(tree->ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace plsm
|
} // namespace plsm
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "Analysis.h"
|
#include "Analysis.h"
|
||||||
|
#include "Errors.h"
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
|
|
||||||
static std::string readFile(const std::string &path) {
|
static std::string readFile(const std::string &path) {
|
||||||
@ -25,21 +26,36 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// std::cout << input << std::endl;
|
// std::cout << input << std::endl;
|
||||||
|
|
||||||
|
int exitStatus = EXIT_SUCCESS;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto module = plsm::parse(argv[1], input);
|
auto module = plsm::parse(argv[1], input);
|
||||||
std::cout << module->toJsonString() << std::endl;
|
// std::cout << module->toJsonString() << std::endl;
|
||||||
|
|
||||||
plsm::performNameAnalysis(module);
|
plsm::performNameAnalysis(module);
|
||||||
|
plsm::performTypeAnalysis(module);
|
||||||
|
|
||||||
// std::cout << "\n\n";
|
// std::cout << "\n\n";
|
||||||
|
|
||||||
// std::cout << plsm::ast::Module::fromJson(module->toJson())->toJson() <<
|
// std::cout << plsm::ast::Module::fromJson(module->toJson())->toJson() <<
|
||||||
// std::endl;
|
// std::endl;
|
||||||
} catch (std::runtime_error &err) {
|
} catch (std::runtime_error &err) {
|
||||||
|
if (strlen(err.what()) > 0)
|
||||||
std::cerr << err.what() << std::endl;
|
std::cerr << err.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exitStatus = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto errors = plsm::errors::get();
|
||||||
|
for (size_t i = 0; i < errors.size(); i++) {
|
||||||
|
exitStatus = EXIT_FAILURE;
|
||||||
|
|
||||||
|
std::cerr << errors[i] << std::endl;
|
||||||
|
if (i != errors.size() - 1)
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(exitStatus);
|
||||||
|
|
||||||
// auto module = Parser().parse(argv[1], readFile(argv[1]));
|
// auto module = Parser().parse(argv[1], readFile(argv[1]));
|
||||||
|
|
||||||
// auto fn = (ast::FnDef *)module->stmts.at(0);
|
// auto fn = (ast::FnDef *)module->stmts.at(0);
|
||||||
|
@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
"@type": "Module",
|
|
||||||
"name": "default",
|
|
||||||
"imports": [],
|
|
||||||
"stmts": [
|
|
||||||
{
|
|
||||||
"@type": "FnDecl",
|
|
||||||
"name": "main",
|
|
||||||
"params": [],
|
|
||||||
"returnTypeName": {
|
|
||||||
"@type": "PrimitiveTypeName",
|
|
||||||
"name": "i64"
|
|
||||||
},
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"@type": "VarDecl",
|
|
||||||
"name": "asdf",
|
|
||||||
"typeName": {
|
|
||||||
"@type": "PrimitiveTypeName",
|
|
||||||
"name": "int"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@type": "AssignStmt",
|
|
||||||
"lval": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "asdf"
|
|
||||||
},
|
|
||||||
"rval": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@type": "IfStmt",
|
|
||||||
"condition": {
|
|
||||||
"@type": "BinExpr",
|
|
||||||
"op": ">",
|
|
||||||
"lhs": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "asdf"
|
|
||||||
},
|
|
||||||
"rhs": 1000
|
|
||||||
},
|
|
||||||
"ifBody": [
|
|
||||||
{
|
|
||||||
"@type": "AssignStmt",
|
|
||||||
"lval": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "a"
|
|
||||||
},
|
|
||||||
"rval": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"elseBody": [
|
|
||||||
{
|
|
||||||
"@type": "IfStmt",
|
|
||||||
"condition": {
|
|
||||||
"@type": "BinExpr",
|
|
||||||
"op": ">",
|
|
||||||
"lhs": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "asdf"
|
|
||||||
},
|
|
||||||
"rhs": 500
|
|
||||||
},
|
|
||||||
"ifBody": [
|
|
||||||
{
|
|
||||||
"@type": "AssignStmt",
|
|
||||||
"lval": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "a"
|
|
||||||
},
|
|
||||||
"rval": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"elseBody": [
|
|
||||||
{
|
|
||||||
"@type": "AssignStmt",
|
|
||||||
"lval": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "a"
|
|
||||||
},
|
|
||||||
"rval": 3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@type": "WhileStmt",
|
|
||||||
"condition": {
|
|
||||||
"@type": "BinExpr",
|
|
||||||
"op": "<",
|
|
||||||
"lhs": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "a"
|
|
||||||
},
|
|
||||||
"rhs": 10
|
|
||||||
},
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"@type": "AssignStmt",
|
|
||||||
"lval": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "a"
|
|
||||||
},
|
|
||||||
"rval": {
|
|
||||||
"@type": "Identifier",
|
|
||||||
"name": "a"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@type": "ExprStmt",
|
|
||||||
"expr": {
|
|
||||||
"@type": "UnExpr",
|
|
||||||
"op": "+",
|
|
||||||
"expr": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@type": "RetStmt",
|
|
||||||
"value": {
|
|
||||||
"@type": "BinExpr",
|
|
||||||
"op": "+",
|
|
||||||
"lhs": {
|
|
||||||
"@type": "BinExpr",
|
|
||||||
"op": "*",
|
|
||||||
"lhs": 3,
|
|
||||||
"rhs": 10
|
|
||||||
},
|
|
||||||
"rhs": {
|
|
||||||
"@type": "BinExpr",
|
|
||||||
"op": "*",
|
|
||||||
"lhs": 21,
|
|
||||||
"rhs": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
@ -1,6 +1,8 @@
|
|||||||
fun main() i64 {
|
var asdf : i64;
|
||||||
var asdf : int;
|
|
||||||
asdf = 100;
|
fun main(arg0 i64) i8 {
|
||||||
|
var a : i64;
|
||||||
|
a = 10 + 2;
|
||||||
|
|
||||||
if (asdf > 1000) {
|
if (asdf > 1000) {
|
||||||
a = 1;
|
a = 1;
|
||||||
@ -10,9 +12,5 @@ fun main() i64 {
|
|||||||
a = 3;
|
a = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (a < 10) {
|
ret 100;
|
||||||
a = a + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret 3 * 10 + 21.0 * 2;
|
|
||||||
}
|
}
|
||||||
|
4
examples/new1.plsm
Normal file
4
examples/new1.plsm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fun main() i64 {
|
||||||
|
var a : int;
|
||||||
|
ret a;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user