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} | ||||
|   COMMENT "Generating plsm_parser" | ||||
|   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 | ||||
|     -o ${GEN_DIR} -Dlanguage=Cpp -no-listener -visitor | ||||
|   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_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src) | ||||
| # set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git) | ||||
| set(ANTLR4_ZIP_REPOSITORY ${PROJECT_SOURCE_DIR}/thirdparty/antlr-4.13.1.zip) | ||||
| set(ANTLR4_ZIP_REPOSITORY ${PROJECT_SOURCE_DIR}/thirdparty/antlr4-4.13.2.zip) | ||||
| if(NOT DEFINED ANTLR4_TAG) | ||||
|   # Set to branch name to keep library updated at the cost of needing to rebuild after 'clean' | ||||
|   # Set to commit hash to keep the build stable and does not need to rebuild after 'clean' | ||||
| @ -47,7 +47,7 @@ else() | ||||
|     set(ANTLR4_SHARED_LIBRARIES | ||||
|         ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a) | ||||
|     set(ANTLR4_RUNTIME_LIBRARIES | ||||
|         ${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.13.1.dll) | ||||
|         ${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.13.2.dll) | ||||
|   elseif(APPLE) | ||||
|     set(ANTLR4_RUNTIME_LIBRARIES | ||||
|         ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib) | ||||
|  | ||||
| @ -14,6 +14,7 @@ | ||||
| #include "Module/Module.h" | ||||
| 
 | ||||
| #include "Stmt/AssignStmt.h" | ||||
| #include "Stmt/Block.h" | ||||
| #include "Stmt/ExprStmt.h" | ||||
| #include "Stmt/FnDecl.h" | ||||
| #include "Stmt/IfStmt.h" | ||||
| @ -24,4 +25,4 @@ | ||||
| #include "Type/FunctionType.h" | ||||
| #include "Type/PrimitiveType.h" | ||||
| 
 | ||||
| #include "TypeName/PrimitiveTypeName.h" | ||||
| #include "TypeName/NamedTypeName.h" | ||||
|  | ||||
| @ -3,15 +3,17 @@ | ||||
| #include <any> | ||||
| #include <boost/json/serialize.hpp> | ||||
| #include <exception> | ||||
| #include <functional> | ||||
| #include <iostream> | ||||
| #include <memory> | ||||
| #include <sstream> | ||||
| #include <stdexcept> | ||||
| #include <string> | ||||
| #include <utility> | ||||
| 
 | ||||
| #include <boost/json.hpp> | ||||
| 
 | ||||
| #include "Terminal.h" | ||||
| 
 | ||||
| #define LOC_ARG const SourceRange &sourceRange | ||||
| 
 | ||||
| namespace plsm { | ||||
| @ -30,6 +32,7 @@ class Import; | ||||
| class Module; | ||||
| 
 | ||||
| class AssignStmt; | ||||
| class Block; | ||||
| class ExprStmt; | ||||
| class FnParam; | ||||
| class FnDecl; | ||||
| @ -38,7 +41,7 @@ class RetStmt; | ||||
| class VarDecl; | ||||
| class WhileStmt; | ||||
| 
 | ||||
| class PrimitiveTypeName; | ||||
| class NamedTypeName; | ||||
| 
 | ||||
| class ASTVisitor { | ||||
| public: | ||||
| @ -57,6 +60,7 @@ public: | ||||
|   virtual std::any visit(Module &module, 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(FnParam &fnParam, 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(WhileStmt &whileStmt, std::any param) = 0; | ||||
| 
 | ||||
|   virtual std::any visit(PrimitiveTypeName &primitiveTypeName, | ||||
|                          std::any param) = 0; | ||||
|   virtual std::any visit(NamedTypeName &namedTypeName, std::any param) = 0; | ||||
| }; | ||||
| 
 | ||||
| } // namespace ast
 | ||||
| @ -79,7 +82,7 @@ class Jsonable { | ||||
| public: | ||||
|   virtual ~Jsonable() = default; | ||||
| 
 | ||||
|   virtual boost::json::value toJson() = 0; | ||||
|   virtual boost::json::value toJson() const = 0; | ||||
| 
 | ||||
| protected: | ||||
|   template <class CurrNode> | ||||
| @ -114,7 +117,8 @@ protected: | ||||
|   template <class CurrNode, class SubNode> | ||||
|   static inline auto fromJsonProperty(boost::json::value json, | ||||
|                                       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> | ||||
| @ -122,9 +126,9 @@ protected: | ||||
|                                     std::string property) { | ||||
|     auto arr = getJsonProperty<CurrNode>(json, property).as_array(); | ||||
| 
 | ||||
|     std::vector<SubNode *> result; | ||||
|     std::vector<std::unique_ptr<SubNode>> result; | ||||
|     for (auto &el : arr) { | ||||
|       result.push_back(SubNode::fromJson(el)); | ||||
|       result.push_back(std::unique_ptr<SubNode>(SubNode::fromJson(el))); | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| @ -133,7 +137,7 @@ protected: | ||||
| 
 | ||||
| class SourceRange { | ||||
| 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) | ||||
|       : file(file), text(text), start(start), end(end) {} | ||||
| 
 | ||||
| @ -141,27 +145,34 @@ public: | ||||
|   const std::pair<size_t, size_t> start, end; | ||||
| 
 | ||||
|   static SourceRange unknown() { | ||||
|     return SourceRange("<?>", "<?>", {-1, -1}, {-1, -1}); | ||||
|     return SourceRange("<?>", "<?>", {0, 0}, {0, 0}); | ||||
|   }; | ||||
| 
 | ||||
|   static SourceRange json() { | ||||
|     return SourceRange("<json>", "<?>", {-1, -1}, {-1, -1}); | ||||
|     return SourceRange("<json>", "<json>", {0, 0}, {0, 0}); | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| class TypeName; | ||||
| 
 | ||||
| class Type : public Jsonable { | ||||
| public: | ||||
|   Type() : Jsonable() {} | ||||
|   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); | ||||
| }; | ||||
| 
 | ||||
| class Symbol { | ||||
| public: | ||||
|   const std::string name; | ||||
|   std::shared_ptr<Type> type; | ||||
| 
 | ||||
| public: | ||||
|   Symbol(const std::string &name) : name(name) {} | ||||
|   Symbol(const std::string &name, Type *type) : name(name), type(type) {} | ||||
| }; | ||||
| @ -173,29 +184,40 @@ public: | ||||
| 
 | ||||
|   const SourceRange sourceRange; | ||||
| 
 | ||||
|   virtual std::string toJsonString() { | ||||
|   virtual std::string toJsonString() const { | ||||
|     return boost::json::serialize(toJson(), {}); | ||||
|   } | ||||
| 
 | ||||
|   static ASTNode *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual bool isExpr() { return false; } | ||||
|   virtual bool isStmt() { return false; } | ||||
|   virtual bool isTypeName() { return false; } | ||||
|   virtual bool isExpr() const { return false; } | ||||
|   virtual bool isStmt() const { 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; | ||||
| }; | ||||
| 
 | ||||
| class Expr : public ASTNode { | ||||
| public: | ||||
|   std::shared_ptr<Type> type; | ||||
| 
 | ||||
| public: | ||||
|   Expr(LOC_ARG) : ASTNode(sourceRange) {} | ||||
|   virtual ~Expr() = default; | ||||
| 
 | ||||
|   static Expr *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual bool isExpr() override { return true; } | ||||
|   virtual bool isExpr() const override { return true; } | ||||
| }; | ||||
| 
 | ||||
| class Stmt : public ASTNode { | ||||
| @ -205,17 +227,19 @@ public: | ||||
| 
 | ||||
|   static Stmt *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual bool isStmt() override { return true; } | ||||
|   virtual bool isStmt() const override { return true; } | ||||
| }; | ||||
| 
 | ||||
| class TypeName : public ASTNode { | ||||
| public: | ||||
|   std::shared_ptr<Type> type; | ||||
| 
 | ||||
|   TypeName(LOC_ARG) : ASTNode(sourceRange) {} | ||||
|   virtual ~TypeName() = default; | ||||
| 
 | ||||
|   static TypeName *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual bool isTypeName() override { return true; } | ||||
|   virtual bool isTypeName() const override { return true; } | ||||
| }; | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -10,24 +10,30 @@ public: | ||||
|   BaseASTVisitor() : ASTVisitor() {}; | ||||
| 
 | ||||
|   virtual std::any visit(BinExpr &binExpr, std::any param) override { | ||||
|     binExpr.lhs->accept(this, param); | ||||
|     binExpr.rhs->accept(this, param); | ||||
|     if (binExpr.lhs.get()) | ||||
|       binExpr.lhs->accept(this, param); | ||||
|     if (binExpr.rhs.get()) | ||||
|       binExpr.rhs->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(CallExpr &callExpr, std::any param) override { | ||||
|     callExpr.callee->accept(this, param); | ||||
|     if (callExpr.callee.get()) | ||||
|       callExpr.callee->accept(this, param); | ||||
| 
 | ||||
|     for (auto &arg : callExpr.args) { | ||||
|       arg->accept(this, param); | ||||
|       if (arg.get()) | ||||
|         arg->accept(this, param); | ||||
|     } | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(CastExpr &castExpr, std::any param) override { | ||||
|     castExpr.value->accept(this, param); | ||||
|     castExpr.typeName->accept(this, param); | ||||
|     if (castExpr.value.get()) | ||||
|       castExpr.value->accept(this, param); | ||||
|     if (castExpr.typeName.get()) | ||||
|       castExpr.typeName->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
| @ -36,19 +42,23 @@ public: | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(LambdaExpr &lambdaExpr, std::any param) override { | ||||
|     for (auto ¶m : lambdaExpr.params) { | ||||
|       param->accept(this, param); | ||||
|     if (lambdaExpr.returnTypeName.get()) | ||||
|       lambdaExpr.returnTypeName->accept(this, param); | ||||
| 
 | ||||
|     for (auto &p : lambdaExpr.params) { | ||||
|       if (p.get()) | ||||
|         p->accept(this, param); | ||||
|     } | ||||
| 
 | ||||
|     for (auto &body : lambdaExpr.body) { | ||||
|       body->accept(this, param); | ||||
|     } | ||||
|     if (lambdaExpr.body.get()) | ||||
|       lambdaExpr.body->accept(this, param); | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(UnExpr &unExpr, std::any param) override { | ||||
|     unExpr.expr->accept(this, param); | ||||
|     if (unExpr.expr.get()) | ||||
|       unExpr.expr->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
| @ -70,75 +80,90 @@ public: | ||||
|     } | ||||
| 
 | ||||
|     for (auto &stmt : module.stmts) { | ||||
|       stmt->accept(this, param); | ||||
|       if (stmt.get()) | ||||
|         stmt->accept(this, param); | ||||
|     } | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(AssignStmt &assignStmt, std::any param) override { | ||||
|     assignStmt.lval->accept(this, param); | ||||
|     assignStmt.rval->accept(this, param); | ||||
|     if (assignStmt.lval.get()) | ||||
|       assignStmt.lval->accept(this, param); | ||||
|     if (assignStmt.rval.get()) | ||||
|       assignStmt.rval->accept(this, param); | ||||
|     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 { | ||||
|     exprStmt.expr->accept(this, param); | ||||
|     if (exprStmt.expr.get()) | ||||
|       exprStmt.expr->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(FnParam &fnParam, std::any param) override { | ||||
|     fnParam.typeName->accept(this, param); | ||||
|     if (fnParam.typeName.get()) | ||||
|       fnParam.typeName->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(FnDecl &fnDecl, std::any param) override { | ||||
|     for (auto ¶m : fnDecl.params) { | ||||
|       param->accept(this, param); | ||||
|     if (fnDecl.returnTypeName.get()) | ||||
|       fnDecl.returnTypeName->accept(this, param); | ||||
| 
 | ||||
|     for (auto &p : fnDecl.params) { | ||||
|       if (p.get()) | ||||
|         p->accept(this, param); | ||||
|     } | ||||
| 
 | ||||
|     for (auto &body : fnDecl.body) { | ||||
|       body->accept(this, param); | ||||
|     } | ||||
|     if (fnDecl.body.get()) | ||||
|       fnDecl.body->accept(this, param); | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(IfStmt &ifStmt, std::any param) override { | ||||
|     ifStmt.condition->accept(this, param); | ||||
| 
 | ||||
|     for (auto &ifBody : ifStmt.ifBody) { | ||||
|       ifBody->accept(this, param); | ||||
|     } | ||||
| 
 | ||||
|     for (auto &elseBody : ifStmt.elseBody) { | ||||
|       elseBody->accept(this, param); | ||||
|     } | ||||
|     if (ifStmt.condition.get()) | ||||
|       ifStmt.condition->accept(this, param); | ||||
|     if (ifStmt.ifBody.get()) | ||||
|       ifStmt.ifBody->accept(this, param); | ||||
|     if (ifStmt.elseBody.get()) | ||||
|       ifStmt.elseBody->accept(this, param); | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(RetStmt &retStmt, std::any param) override { | ||||
|     retStmt.value->accept(this, param); | ||||
|     if (retStmt.value.get()) | ||||
|       retStmt.value->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(VarDecl &varDecl, std::any param) override { | ||||
|     varDecl.typeName->accept(this, param); | ||||
|     if (varDecl.typeName.get()) | ||||
|       varDecl.typeName->accept(this, param); | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(WhileStmt &whileStmt, std::any param) override { | ||||
|     whileStmt.condition->accept(this, param); | ||||
| 
 | ||||
|     for (auto &body : whileStmt.body) { | ||||
|       body->accept(this, param); | ||||
|     } | ||||
|     if (whileStmt.condition.get()) | ||||
|       whileStmt.condition->accept(this, param); | ||||
|     if (whileStmt.body.get()) | ||||
|       whileStmt.body->accept(this, param); | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| 
 | ||||
|   virtual std::any visit(PrimitiveTypeName &primitiveTypeName, | ||||
|   virtual std::any visit(NamedTypeName &namedTypeName, | ||||
|                          std::any param) override { | ||||
|     return std::any(); | ||||
|   } | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| @ -28,12 +27,17 @@ enum BinOp { | ||||
| class BinExpr : public Expr { | ||||
| public: | ||||
|   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) | ||||
|       : Expr(sourceRange), op(op), lhs(lhs), rhs(rhs) {} | ||||
|   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() 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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -9,17 +9,14 @@ namespace ast { | ||||
| 
 | ||||
| class CallExpr : public Expr { | ||||
| public: | ||||
|   const std::shared_ptr<Expr> callee; | ||||
|   std::vector<std::shared_ptr<Expr>> args; | ||||
|   std::unique_ptr<Expr> callee; | ||||
|   std::vector<std::unique_ptr<Expr>> args; | ||||
| 
 | ||||
|   CallExpr(LOC_ARG, Expr *callee, std::vector<Expr *> args) | ||||
|       : Expr(sourceRange), callee(callee), args() { | ||||
|     for (auto &arg : args) { | ||||
|       this->args.push_back(std::shared_ptr<Expr>(arg)); | ||||
|     } | ||||
|   } | ||||
|   CallExpr(LOC_ARG, std::unique_ptr<Expr> callee, | ||||
|            std::vector<std::unique_ptr<Expr>> args) | ||||
|       : Expr(sourceRange), callee(std::move(callee)), args(std::move(args)) {} | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static CallExpr *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -1,20 +1,21 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <string> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| class CastExpr : public Expr { | ||||
| public: | ||||
|   const std::shared_ptr<Expr> value; | ||||
|   const std::shared_ptr<TypeName> typeName; | ||||
|   std::unique_ptr<Expr> value; | ||||
|   std::unique_ptr<TypeName> typeName; | ||||
| 
 | ||||
|   CastExpr(LOC_ARG, Expr *value, TypeName *typeName) | ||||
|       : Expr(sourceRange), value(value), typeName(typeName) {} | ||||
|   CastExpr(LOC_ARG, std::unique_ptr<Expr> value, | ||||
|            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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -14,7 +14,7 @@ public: | ||||
|   Identifier(LOC_ARG, const std::string &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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace plsm { | ||||
| @ -11,21 +10,17 @@ class FnParam; | ||||
| 
 | ||||
| class LambdaExpr : public Expr { | ||||
| public: | ||||
|   std::vector<std::shared_ptr<FnParam>> params; | ||||
|   std::vector<std::shared_ptr<Expr>> body; | ||||
|   std::vector<std::unique_ptr<FnParam>> params; | ||||
|   std::unique_ptr<TypeName> returnTypeName; | ||||
|   std::unique_ptr<Block> body; | ||||
| 
 | ||||
|   LambdaExpr(LOC_ARG, std::vector<FnParam *> params, std::vector<Expr *> body) | ||||
|       : Expr(sourceRange), params(), body() { | ||||
|     for (auto ¶m : params) { | ||||
|       this->params.push_back(std::shared_ptr<FnParam>(param)); | ||||
|     } | ||||
|   LambdaExpr(LOC_ARG, std::vector<std::unique_ptr<FnParam>> params, | ||||
|              std::unique_ptr<TypeName> returnTypeName, | ||||
|              std::unique_ptr<Block> body) | ||||
|       : Expr(sourceRange), params(std::move(params)), | ||||
|         returnTypeName(std::move(returnTypeName)), body(std::move(body)) {} | ||||
| 
 | ||||
|     for (auto &expr : body) { | ||||
|       this->body.push_back(std::shared_ptr<Expr>(expr)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static LambdaExpr *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| @ -15,12 +14,12 @@ enum UnOp { | ||||
| class UnExpr : public Expr { | ||||
| public: | ||||
|   const UnOp op; | ||||
|   const std::shared_ptr<Expr> expr; | ||||
|   std::unique_ptr<Expr> expr; | ||||
| 
 | ||||
|   UnExpr(LOC_ARG, const UnOp op, Expr *expr) | ||||
|       : Expr(sourceRange), op(op), expr(expr) {} | ||||
|   UnExpr(LOC_ARG, const UnOp op, std::unique_ptr<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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -3,7 +3,6 @@ | ||||
| #include "AST/Base.h" | ||||
| #include <cfloat> | ||||
| #include <cstdint> | ||||
| #include <string> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| @ -11,7 +10,7 @@ namespace ast { | ||||
| // public:
 | ||||
| //   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);
 | ||||
| // };
 | ||||
| 
 | ||||
| @ -21,7 +20,7 @@ public: | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
| @ -35,7 +34,7 @@ public: | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -12,7 +12,7 @@ public: | ||||
|   Import(LOC_ARG, const std::string &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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -11,22 +11,16 @@ class Import; | ||||
| class Module : public ASTNode { | ||||
| public: | ||||
|   const std::string name; | ||||
|   std::vector<std::shared_ptr<Import>> imports; | ||||
|   std::vector<std::shared_ptr<Stmt>> stmts; | ||||
|   std::vector<std::unique_ptr<Import>> imports; | ||||
|   std::vector<std::unique_ptr<Stmt>> stmts; | ||||
| 
 | ||||
|   Module(LOC_ARG, const std::string &name, const std::vector<Import *> &imports, | ||||
|          const std::vector<Stmt *> &stmts) | ||||
|       : ASTNode(sourceRange), name(name), imports(), stmts() { | ||||
|     for (auto &import : imports) { | ||||
|       this->imports.push_back(std::shared_ptr<Import>(import)); | ||||
|     } | ||||
|   Module(LOC_ARG, const std::string &name, | ||||
|          std::vector<std::unique_ptr<Import>> imports, | ||||
|          std::vector<std::unique_ptr<Stmt>> stmts) | ||||
|       : ASTNode(sourceRange), name(name), imports(std::move(imports)), | ||||
|         stmts(std::move(stmts)) {} | ||||
| 
 | ||||
|     for (auto &stmt : stmts) { | ||||
|       this->stmts.push_back(std::shared_ptr<Stmt>(stmt)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static Module *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -2,20 +2,19 @@ | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| class AssignStmt : public Stmt { | ||||
| public: | ||||
|   const std::shared_ptr<Expr> lval; | ||||
|   const std::shared_ptr<Expr> rval; | ||||
|   std::unique_ptr<Expr> lval; | ||||
|   std::unique_ptr<Expr> rval; | ||||
| 
 | ||||
|   AssignStmt(LOC_ARG, Expr *lval, Expr *rval) | ||||
|       : Stmt(sourceRange), lval(lval), rval(rval) {} | ||||
|   AssignStmt(LOC_ARG, std::unique_ptr<Expr> lval, std::unique_ptr<Expr> 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); | ||||
| 
 | ||||
|   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 { | ||||
| class ExprStmt : public Stmt { | ||||
| 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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -11,14 +11,14 @@ namespace ast { | ||||
| class FnParam : public ASTNode { | ||||
| public: | ||||
|   const std::string name; | ||||
|   const std::shared_ptr<TypeName> typeName; | ||||
|   std::unique_ptr<TypeName> typeName; | ||||
| 
 | ||||
|   std::shared_ptr<Symbol> symbol; | ||||
| 
 | ||||
|   FnParam(LOC_ARG, const std::string &name, TypeName *typeName) | ||||
|       : ASTNode(sourceRange), name(name), typeName(typeName) {} | ||||
|   FnParam(LOC_ARG, const std::string &name, std::unique_ptr<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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
| @ -29,26 +29,19 @@ public: | ||||
| class FnDecl : public Stmt { | ||||
| public: | ||||
|   const std::string name; | ||||
|   std::vector<std::shared_ptr<FnParam>> params; | ||||
|   const std::shared_ptr<TypeName> returnTypeName; | ||||
|   std::vector<std::shared_ptr<Stmt>> body; | ||||
|   std::vector<std::unique_ptr<FnParam>> params; | ||||
|   std::unique_ptr<TypeName> returnTypeName; | ||||
|   std::unique_ptr<Block> body; | ||||
| 
 | ||||
|   std::shared_ptr<Symbol> symbol; | ||||
| 
 | ||||
|   FnDecl(LOC_ARG, const std::string &name, const std::vector<FnParam *> ¶ms, | ||||
|          TypeName *returnTypeName, const std::vector<Stmt *> &body) | ||||
|       : Stmt(sourceRange), name(name), params(), returnTypeName(returnTypeName), | ||||
|         body() { | ||||
|     for (auto ¶m : params) { | ||||
|       this->params.push_back(std::shared_ptr<FnParam>(param)); | ||||
|     } | ||||
|   FnDecl(LOC_ARG, const std::string &name, | ||||
|          std::vector<std::unique_ptr<FnParam>> params, | ||||
|          std::unique_ptr<TypeName> returnTypeName, std::unique_ptr<Block> body) | ||||
|       : Stmt(sourceRange), name(name), params(std::move(params)), | ||||
|         returnTypeName(std::move(returnTypeName)), body(std::move(body)) {} | ||||
| 
 | ||||
|     for (auto &stmt : body) { | ||||
|       this->body.push_back(std::shared_ptr<Stmt>(stmt)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static FnDecl *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -2,29 +2,21 @@ | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| class IfStmt : public Stmt { | ||||
| public: | ||||
|   const std::shared_ptr<Expr> condition; | ||||
|   std::vector<std::shared_ptr<Stmt>> ifBody, elseBody; | ||||
|   std::unique_ptr<Expr> condition; | ||||
|   std::unique_ptr<Block> ifBody, elseBody; | ||||
| 
 | ||||
|   IfStmt(LOC_ARG, Expr *condition, const std::vector<Stmt *> &ifBody, | ||||
|          const std::vector<Stmt *> &elseBody) | ||||
|       : Stmt(sourceRange), condition(condition) { | ||||
|     for (auto &stmt : ifBody) { | ||||
|       this->ifBody.push_back(std::shared_ptr<Stmt>(stmt)); | ||||
|     } | ||||
|   IfStmt(LOC_ARG, std::unique_ptr<Expr> condition, | ||||
|          std::unique_ptr<Block> ifBody, std::unique_ptr<Block> elseBody) | ||||
|       : Stmt(sourceRange), condition(std::move(condition)), | ||||
|         ifBody(std::move(ifBody)), elseBody(std::move(elseBody)) {} | ||||
| 
 | ||||
|     for (auto &stmt : elseBody) { | ||||
|       this->elseBody.push_back(std::shared_ptr<Stmt>(stmt)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static IfStmt *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -7,11 +7,12 @@ namespace plsm { | ||||
| namespace ast { | ||||
| class RetStmt : public Stmt { | ||||
| 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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -10,14 +10,14 @@ namespace ast { | ||||
| class VarDecl : public Stmt { | ||||
| public: | ||||
|   const std::string name; | ||||
|   const std::shared_ptr<TypeName> typeName; | ||||
|   std::unique_ptr<TypeName> typeName; | ||||
| 
 | ||||
|   std::shared_ptr<Symbol> symbol; | ||||
| 
 | ||||
|   VarDecl(LOC_ARG, const std::string &name, TypeName *typeName) | ||||
|       : Stmt(sourceRange), name(name), typeName(typeName) {} | ||||
|   VarDecl(LOC_ARG, const std::string &name, std::unique_ptr<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); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|  | ||||
| @ -2,28 +2,26 @@ | ||||
| 
 | ||||
| #include "AST/Base.h" | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| class WhileStmt : public Stmt { | ||||
| public: | ||||
|   const std::shared_ptr<Expr> condition; | ||||
|   std::vector<std::shared_ptr<Stmt>> body; | ||||
|   std::unique_ptr<Expr> condition; | ||||
|   std::unique_ptr<Block> body; | ||||
| 
 | ||||
|   WhileStmt(LOC_ARG, Expr *condition, const std::vector<Stmt *> &body) | ||||
|       : Stmt(sourceRange), condition(condition) { | ||||
|     for (auto &stmt : body) { | ||||
|       this->body.push_back(std::shared_ptr<Stmt>(stmt)); | ||||
|     } | ||||
|   } | ||||
|   WhileStmt(LOC_ARG, std::unique_ptr<Expr> condition, | ||||
|             std::unique_ptr<Block> body) | ||||
|       : Stmt(sourceRange), condition(std::move(condition)), | ||||
|         body(std::move(body)) {} | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static WhileStmt *fromJson(boost::json::value json); | ||||
| 
 | ||||
|   virtual std::any accept(ASTVisitor *visitor, std::any param) override { | ||||
|     return visitor->visit(*this, param); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| } // namespace ast
 | ||||
| } // namespace plsm
 | ||||
|  | ||||
| @ -11,14 +11,36 @@ public: | ||||
|   std::vector<std::shared_ptr<Type>> paramTypes; | ||||
|   const std::shared_ptr<Type> returnType; | ||||
| 
 | ||||
|   FunctionType(const std::vector<Type *> ¶mTypes, Type *returnType) | ||||
|       : Type(), returnType(returnType) { | ||||
|     for (auto ¶mType : paramTypes) { | ||||
|       this->paramTypes.push_back(std::shared_ptr<Type>(paramType)); | ||||
|   FunctionType(std::vector<std::shared_ptr<Type>> paramTypes, | ||||
|                std::shared_ptr<Type> returnType) | ||||
|       : Type(), paramTypes(paramTypes), returnType(returnType) {} | ||||
| 
 | ||||
|   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; | ||||
|       } | ||||
| 
 | ||||
|       return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   virtual boost::json::value toJson() override; | ||||
|   virtual boost::json::value toJson() const override; | ||||
|   static FunctionType *fromJson(boost::json::value json); | ||||
| }; | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -11,10 +11,17 @@ public: | ||||
| 
 | ||||
|   PrimitiveType(const std::string &name) : Type(), name(name) {} | ||||
| 
 | ||||
|   bool operator==(const PrimitiveType &other) { return name == other.name; } | ||||
|   bool operator!=(const PrimitiveType &other) { return !(*this == other); } | ||||
|   virtual TypeName *toTypeName() override; | ||||
| 
 | ||||
|   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); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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 { | ||||
| 
 | ||||
| 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" | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
|  | ||||
							
								
								
									
										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 <functional> | ||||
| #include <vector> | ||||
| @ -5,7 +7,7 @@ | ||||
| namespace plsm { | ||||
| 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()); | ||||
|   for (size_t i = 0; i < vector.size(); i++) | ||||
|     result[i] = vector[i]->toJson(); | ||||
| @ -13,12 +15,30 @@ template <typename T> auto mapToJson(const std::vector<T> &vector) { | ||||
| } | ||||
| 
 | ||||
| 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()); | ||||
|   for (size_t i = 0; i < vector.size(); i++) | ||||
|     result[i] = mapper(vector[i]); | ||||
|   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 plsm
 | ||||
|  | ||||
							
								
								
									
										244
									
								
								compiler/plsm.g4
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								compiler/plsm.g4
									
									
									
									
									
								
							| @ -2,189 +2,199 @@ grammar plsm; | ||||
| 
 | ||||
| @parser::header { | ||||
| #include "AST/AST.h" | ||||
| #include "Utils.h" | ||||
| #include <memory> | ||||
| #include <boost/algorithm/string.hpp> | ||||
| 
 | ||||
| using namespace plsm::utils; | ||||
| using namespace plsm::ast; | ||||
| } | ||||
| 
 | ||||
| @parser::members { | ||||
|   std::string filename, sourceText; | ||||
| 
 | ||||
| std::string filename; | ||||
|   void setFileName(const std::string &filename) { this->filename = filename; } | ||||
|   void setSourceText(const std::string &sourceText) { this->sourceText = sourceText; } | ||||
| 
 | ||||
| void setFileName(const std::string &filename) { this->filename = filename; } | ||||
|   inline SourceRange getSourceRange(antlr4::ParserRuleContext *ctx) { | ||||
|     auto start = ctx->start; | ||||
|     auto stop = getCurrentToken(); | ||||
| 
 | ||||
| inline SourceRange getSourceRange(antlr4::ParserRuleContext *ctx) { | ||||
|      if (!ctx->getStart() || !ctx->getStop()) { | ||||
|           return SourceRange::unknown(); | ||||
|      } | ||||
|     auto startPos = std::pair<size_t, size_t>(start->getLine(), | ||||
|                                               start->getCharPositionInLine()); | ||||
|     auto stopPos = std::pair<size_t, size_t>(stop->getLine(), | ||||
|                                              stop->getCharPositionInLine()); | ||||
| 
 | ||||
|      return SourceRange( | ||||
|           filename, ctx->getText(), | ||||
|           std::pair<size_t, size_t>(ctx->getStart()->getLine(), | ||||
|                                     ctx->getStart()->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 | ||||
| 	returns[Module *ast]: (stmts += topLevelStmt)* { | ||||
|           std::vector<Stmt *> stmts; | ||||
| 	returns[std::unique_ptr<Module> ast]: (stmts += topLevelStmt)* EOF { | ||||
|           std::vector<std::unique_ptr<Stmt>> 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 | ||||
| 	returns[Stmt *ast]: | ||||
| 	returns[std::unique_ptr<Stmt> ast]: | ||||
| 	varDecl { | ||||
|           $ast = $ctx->varDecl()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->varDecl()->ast); | ||||
|      } | ||||
| 	| 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 | ||||
| 	returns[Stmt *ast]: | ||||
| 	returns[std::unique_ptr<Stmt> ast]: | ||||
| 	exprStmt { | ||||
|           $ast = $ctx->exprStmt()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->exprStmt()->ast); | ||||
|      } | ||||
| 	| varDecl { | ||||
|           $ast = $ctx->varDecl()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->varDecl()->ast); | ||||
|      } | ||||
| 	| retStmt { | ||||
|           $ast = $ctx->retStmt()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->retStmt()->ast); | ||||
|      } | ||||
| 	| assignStmt { | ||||
|           $ast = $ctx->assignStmt()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->assignStmt()->ast); | ||||
|      } | ||||
| 	| implDeclAssignStmt { | ||||
|           $ast = $ctx->implDeclAssignStmt()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->implDeclAssignStmt()->ast); | ||||
|      } | ||||
| 	| ifStmt { | ||||
|           $ast = $ctx->ifStmt()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->ifStmt()->ast); | ||||
|      } | ||||
| 	| whileStmt { | ||||
|           $ast = $ctx->whileStmt()->ast; | ||||
|           $ast = ptrcast<Stmt>($ctx->whileStmt()->ast); | ||||
|      }; | ||||
| 
 | ||||
| whileStmt | ||||
| 	returns[WhileStmt *ast]: | ||||
| 	returns[std::unique_ptr<WhileStmt> ast]: | ||||
| 	'while' '(' condition = expr ')' ( | ||||
| 		'{' (stmts += stmt)* '}' | ||||
| 		| singleStmt = stmt | ||||
| 		'{' block '}' | ||||
| 		| 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; | ||||
|           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); | ||||
|           $ast = std::make_unique<WhileStmt>(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(body)); | ||||
|      }; | ||||
| 
 | ||||
| ifStmt | ||||
| 	returns[IfStmt *ast]: | ||||
| 	returns[std::unique_ptr<IfStmt> ast]: | ||||
| 	'if' '(' condition = expr ')' ( | ||||
| 		'{' (ifStmts += stmt)* '}' | ||||
| 		| ifSingleStmt = stmt | ||||
| 		'{' ifBlock = block '}' | ||||
| 		| ifSingleBlock = singleStmtBlock | ||||
| 	) ( | ||||
| 		'else' ( | ||||
| 			'{' (elseStmts += stmt)* '}' | ||||
| 			| elseSingleStmt = stmt | ||||
| 			'{' elseBlock = block '}' | ||||
| 			| 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; | ||||
|           for (auto &stmt : $ctx->ifStmts) { | ||||
|                ifBody.push_back(stmt->ast); | ||||
|           } | ||||
|           if ($ctx->ifSingleStmt) ifBody.push_back($ctx->ifSingleStmt->ast); | ||||
|           std::unique_ptr<Block> elseBody; | ||||
|           if ($ctx->elseBlock) elseBody = std::move($ctx->elseBlock->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>>()); | ||||
| 
 | ||||
| 
 | ||||
|           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); | ||||
|           $ast = std::make_unique<IfStmt>(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(ifBody), std::move(elseBody)); | ||||
|      }; | ||||
| 
 | ||||
| implDeclAssignStmt | ||||
| 	returns[Stmt *ast]: | ||||
| 	returns[std::unique_ptr<Stmt> ast]: | ||||
| 	IDENTIFIER ':=' expr { | ||||
|           // TODO | ||||
|      }; | ||||
| 
 | ||||
| assignStmt | ||||
| 	returns[AssignStmt *ast]: | ||||
| 	lval = expr '=' rval = expr { | ||||
|           $ast = new AssignStmt(getSourceRange($ctx), $ctx->lval->ast, $ctx->rval->ast); | ||||
| 	returns[std::unique_ptr<AssignStmt> ast]: | ||||
| 	lval = expr '=' rval = expr ';' { | ||||
|           $ast = std::make_unique<AssignStmt>(getSourceRange($ctx), std::move($ctx->lval->ast), std::move($ctx->rval->ast)); | ||||
|      }; | ||||
| 
 | ||||
| retStmt | ||||
| 	returns[RetStmt *ast]: | ||||
| 	returns[std::unique_ptr<RetStmt> ast]: | ||||
| 	'ret' expr ';' { | ||||
|           $ast = new RetStmt(getSourceRange($ctx), $ctx->expr()->ast); | ||||
|           $ast = std::make_unique<RetStmt>(getSourceRange($ctx), std::move($ctx->expr()->ast)); | ||||
|      }; | ||||
| 
 | ||||
| fnDecl | ||||
| 	returns[FnDecl *ast]: | ||||
| 	returns[std::unique_ptr<FnDecl> ast]: | ||||
| 	'fun' name = IDENTIFIER '(' ( | ||||
| 		params += fnParam (',' params += fnParam)* | ||||
| 	)? ')' typeName '{' (stmts += stmt)* '}' { | ||||
| 	)? ')' typeName '{' block '}' { | ||||
|           auto name = $ctx->name->getText(); | ||||
| 
 | ||||
|           std::vector<FnParam *> params; | ||||
|           std::vector<std::unique_ptr<FnParam>> params; | ||||
|           for (auto ¶m : $ctx->params) { | ||||
|                params.push_back(param->ast); | ||||
|                params.push_back(std::move(param->ast)); | ||||
|           } | ||||
| 
 | ||||
|           auto returnTypeName = $ctx->typeName()->ast; | ||||
| 
 | ||||
|           std::vector<Stmt *> body; | ||||
|           for (auto &stmt : $ctx->stmts) { | ||||
|                body.push_back(stmt->ast); | ||||
|           } | ||||
| 
 | ||||
|           $ast = new FnDecl(getSourceRange($ctx), name, params, returnTypeName, body); | ||||
|           $ast = std::make_unique<FnDecl>(getSourceRange($ctx), name, std::move(params), std::move($ctx->typeName()->ast), std::move($ctx->block()->ast)); | ||||
|      }; | ||||
| 
 | ||||
| fnParam | ||||
| 	returns[FnParam *ast]: | ||||
| 	returns[std::unique_ptr<FnParam> ast]: | ||||
| 	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 | ||||
| 	returns[VarDecl *ast]: | ||||
| 	returns[std::unique_ptr<VarDecl> ast]: | ||||
| 	'var' IDENTIFIER ':' typeName ';' { | ||||
|           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 | ||||
| 	returns[ExprStmt *ast]: | ||||
| 	returns[std::unique_ptr<ExprStmt> ast]: | ||||
| 	expr ';' { | ||||
|           $ast = new ExprStmt(getSourceRange($ctx), $ctx->expr()->ast); | ||||
|           $ast = std::make_unique<ExprStmt>(getSourceRange($ctx), std::move($ctx->expr()->ast)); | ||||
|      }; | ||||
| 
 | ||||
| expr | ||||
| 	returns[Expr *ast]: | ||||
| 	returns[std::unique_ptr<Expr> ast]: | ||||
| 	value = binaryExpr { | ||||
|           $ast = $ctx->value->ast; | ||||
|           $ast = std::move($ctx->value->ast); | ||||
|      }; | ||||
| 
 | ||||
| binaryExpr | ||||
| 	returns[Expr *ast]: | ||||
| 	returns[std::unique_ptr<Expr> ast]: | ||||
| 	value = unaryExpr { | ||||
|           $ast = $ctx->value->ast; | ||||
|           $ast = std::move($ctx->value->ast); | ||||
|      } | ||||
| 	| lhs = binaryExpr op = ('*' | '/' | '%') rhs = binaryExpr { | ||||
|           auto opText = $ctx->op->getText(); | ||||
| @ -194,7 +204,8 @@ binaryExpr | ||||
|           if (opText == "/") op = BinOp::DIV; | ||||
|           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 { | ||||
|           auto opText = $ctx->op->getText(); | ||||
| @ -203,10 +214,12 @@ binaryExpr | ||||
|           if (opText == "+") op = BinOp::ADD; | ||||
|           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 { | ||||
|           $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 = ( | ||||
| 		'==' | ||||
| @ -226,37 +239,44 @@ binaryExpr | ||||
|           if (opText == ">") op = BinOp::GT; | ||||
|           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 { | ||||
|           $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 { | ||||
|           $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 | ||||
| 	returns[Expr *ast]: | ||||
| 	returns[std::unique_ptr<Expr> ast]: | ||||
| 	factorExpr { | ||||
|           $ast = $ctx->factorExpr()->ast; | ||||
|           $ast = ptrcast<Expr>($ctx->factorExpr()->ast); | ||||
|      } | ||||
| 	| functionCall { | ||||
|           $ast = $ctx->functionCall()->ast; | ||||
|           $ast = ptrcast<Expr>($ctx->functionCall()->ast); | ||||
|      } | ||||
| 	| '!' 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 { | ||||
|           $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 { | ||||
|           $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 | ||||
| 	returns[Expr *ast]: | ||||
| 	returns[std::unique_ptr<Expr> ast]: | ||||
| 	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 { | ||||
|           auto text = $ctx->INT()->getText(); | ||||
| @ -275,7 +295,8 @@ factorExpr | ||||
|           else | ||||
|                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 { | ||||
|           auto text = $ctx->FLOAT()->getText(); | ||||
| @ -286,32 +307,35 @@ factorExpr | ||||
|                text = "0" + text; | ||||
| 
 | ||||
|           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 { | ||||
|           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 ')' { | ||||
|           $ast = $ctx->expr()->ast; | ||||
|           $ast = std::move($ctx->expr()->ast); | ||||
|      }; | ||||
| 
 | ||||
| functionCall | ||||
| 	returns[Expr *ast]: | ||||
| 	returns[std::unique_ptr<CallExpr> ast]: | ||||
| 	callee = factorExpr '(' (args += expr (',' args += expr)*)? ')' { | ||||
|           std::vector<Expr *> args; | ||||
|           std::vector<std::unique_ptr<Expr>> 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 | ||||
| 	returns[TypeName *ast]: | ||||
| 	returns[std::unique_ptr<TypeName> ast]: | ||||
| 	IDENTIFIER { | ||||
|           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]+; | ||||
|  | ||||
| @ -57,8 +57,8 @@ ASTNode *ASTNode::fromJson(boost::json::value json) { | ||||
|   if (type == "WhileStmt") | ||||
|     return WhileStmt::fromJson(json); | ||||
| 
 | ||||
|   if (type == "PrimitiveTypeName") | ||||
|     return PrimitiveTypeName::fromJson(json); | ||||
|   if (type == "NamedTypeName") | ||||
|     return NamedTypeName::fromJson(json); | ||||
| 
 | ||||
|   throw std::runtime_error("json conversion for '" + type + | ||||
|                            "' not implemented"); | ||||
|  | ||||
| @ -18,7 +18,7 @@ static const std::unordered_map<std::string, BinOp> stringToBinOp = { | ||||
|     {"||", BinOp::OR}, | ||||
| }; | ||||
| 
 | ||||
| boost::json::value BinExpr::toJson() { | ||||
| boost::json::value BinExpr::toJson() const { | ||||
|   return { | ||||
|       {"@type", "BinExpr"}, | ||||
|       {"op", binOpToString.at(op)}, | ||||
| @ -34,7 +34,7 @@ BinExpr *BinExpr::fromJson(boost::json::value json) { | ||||
|   auto lhs = fromJsonProperty<BinExpr, Expr>(json, "lhs"); | ||||
|   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
 | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value CallExpr::toJson() { | ||||
| boost::json::value CallExpr::toJson() const { | ||||
|   return { | ||||
|       {"@type", "CallExpr"}, | ||||
|       {"callee", callee->toJson()}, | ||||
| @ -15,7 +15,7 @@ boost::json::value CallExpr::toJson() { | ||||
| CallExpr *CallExpr::fromJson(boost::json::value json) { | ||||
|   auto callee = fromJsonProperty<CallExpr, Expr>(json, "callee"); | ||||
|   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
 | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value CastExpr::toJson() { | ||||
| boost::json::value CastExpr::toJson() const { | ||||
|   return { | ||||
|       {"@type", "CastExpr"}, | ||||
|       {"value", value->toJson()}, | ||||
| @ -15,7 +15,8 @@ boost::json::value CastExpr::toJson() { | ||||
| CastExpr *CastExpr::fromJson(boost::json::value json) { | ||||
|   auto value = fromJsonProperty<CastExpr, Expr>(json, "value"); | ||||
|   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
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value Identifier::toJson() { | ||||
| boost::json::value Identifier::toJson() const { | ||||
|   return { | ||||
|       {"@type", "Identifier"}, | ||||
|       {"name", name}, | ||||
|  | ||||
| @ -4,18 +4,22 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value LambdaExpr::toJson() { | ||||
| boost::json::value LambdaExpr::toJson() const { | ||||
|   return { | ||||
|       {"@type", "LambdaExpr"}, | ||||
|       {"params", utils::mapToJson(params)}, | ||||
|       {"body", utils::mapToJson(body)}, | ||||
|       {"returnTypeName", returnTypeName->toJson()}, | ||||
|       {"body", body->toJson()}, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| LambdaExpr *LambdaExpr::fromJson(boost::json::value json) { | ||||
|   auto params = fromJsonVector<LambdaExpr, FnParam>(json, "params"); | ||||
|   auto body = fromJsonVector<LambdaExpr, Expr>(json, "body"); | ||||
|   return new LambdaExpr(SourceRange::json(), params, body); | ||||
|   auto returnTypeName = | ||||
|       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
 | ||||
|  | ||||
| @ -16,7 +16,7 @@ static const std::unordered_map<std::string, UnOp> stringToUnOp = { | ||||
|     {"!", UnOp::NOT}, | ||||
| }; | ||||
| 
 | ||||
| boost::json::value UnExpr::toJson() { | ||||
| boost::json::value UnExpr::toJson() const { | ||||
|   return { | ||||
|       {"@type", "UnExpr"}, | ||||
|       {"op", unOpToString.at(op)}, | ||||
| @ -29,7 +29,7 @@ UnExpr *UnExpr::fromJson(boost::json::value json) { | ||||
|   auto op = stringToUnOp.at(opString); | ||||
| 
 | ||||
|   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
 | ||||
|  | ||||
| @ -3,20 +3,20 @@ | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| // boost::json::value NullValue::toJson() { return nullptr; }
 | ||||
| // boost::json::value NullValue::toJson() const { return nullptr; }
 | ||||
| 
 | ||||
| // std::unique_ptr<NullValue>
 | ||||
| // NullValue::fromJson(boost::json::value 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) { | ||||
|   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) { | ||||
|   return new FloatValue(SourceRange::json(), json.as_double()); | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value Import::toJson() { | ||||
| boost::json::value Import::toJson() const { | ||||
|   return {{"@type", "Import"}, {"moduleName", moduleName}}; | ||||
| } | ||||
| Import *Import::fromJson(boost::json::value json) { | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value Module::toJson() { | ||||
| boost::json::value Module::toJson() const { | ||||
|   return { | ||||
|       {"@type", "Module"}, | ||||
|       {"name", name}, | ||||
| @ -18,7 +18,8 @@ Module *Module::fromJson(boost::json::value json) { | ||||
|   auto imports = fromJsonVector<Module, Import>(json, "imports"); | ||||
|   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
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value AssignStmt::toJson() { | ||||
| boost::json::value AssignStmt::toJson() const { | ||||
|   return { | ||||
|       {"@type", "AssignStmt"}, | ||||
|       {"lval", lval->toJson()}, | ||||
| @ -14,7 +14,7 @@ boost::json::value AssignStmt::toJson() { | ||||
| AssignStmt *AssignStmt::fromJson(boost::json::value json) { | ||||
|   auto lval = fromJsonProperty<AssignStmt, Expr>(json, "lval"); | ||||
|   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
 | ||||
|  | ||||
							
								
								
									
										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 ast { | ||||
| 
 | ||||
| boost::json::value ExprStmt::toJson() { | ||||
| boost::json::value ExprStmt::toJson() const { | ||||
|   return { | ||||
|       {"@type", "ExprStmt"}, | ||||
|       {"expr", expr->toJson()}, | ||||
| @ -12,7 +12,7 @@ boost::json::value ExprStmt::toJson() { | ||||
| 
 | ||||
| ExprStmt *ExprStmt::fromJson(boost::json::value json) { | ||||
|   auto expr = fromJsonProperty<ExprStmt, Expr>(json, "expr"); | ||||
|   return new ExprStmt(SourceRange::json(), expr); | ||||
|   return new ExprStmt(SourceRange::json(), std::move(expr)); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value FnParam::toJson() { | ||||
| boost::json::value FnParam::toJson() const { | ||||
|   return { | ||||
|       {"@type", "FnParam"}, | ||||
|       {"name", name}, | ||||
| @ -15,16 +15,16 @@ boost::json::value FnParam::toJson() { | ||||
| FnParam *FnParam::fromJson(boost::json::value json) { | ||||
|   auto name = getJsonValue<FnParam, std::string>(json, "name"); | ||||
|   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 { | ||||
|       {"@type", "FnDecl"}, | ||||
|       {"name", name}, | ||||
|       {"params", utils::mapToJson(params)}, | ||||
|       {"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 returnTypeName = | ||||
|       fromJsonProperty<FnDecl, TypeName>(json, "returnTypeName"); | ||||
|   auto body = fromJsonVector<FnDecl, Stmt>(json, "body"); | ||||
|   return new FnDecl(SourceRange::json(), name, params, returnTypeName, body); | ||||
|   auto body = fromJsonProperty<FnDecl, Block>(json, "body"); | ||||
|   return new FnDecl(SourceRange::json(), name, std::move(params), | ||||
|                     std::move(returnTypeName), std::move(body)); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -4,20 +4,21 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value IfStmt::toJson() { | ||||
| boost::json::value IfStmt::toJson() const { | ||||
|   return { | ||||
|       {"@type", "IfStmt"}, | ||||
|       {"condition", condition->toJson()}, | ||||
|       {"ifBody", utils::mapToJson(ifBody)}, | ||||
|       {"elseBody", utils::mapToJson(elseBody)}, | ||||
|       {"ifBody", ifBody->toJson()}, | ||||
|       {"elseBody", elseBody->toJson()}, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| IfStmt *IfStmt::fromJson(boost::json::value json) { | ||||
|   auto condition = fromJsonProperty<IfStmt, Expr>(json, "condition"); | ||||
|   auto ifBody = fromJsonVector<IfStmt, Stmt>(json, "ifBody"); | ||||
|   auto elseBody = fromJsonVector<IfStmt, Stmt>(json, "elseBody"); | ||||
|   return new IfStmt(SourceRange::json(), condition, ifBody, elseBody); | ||||
|   auto ifBody = fromJsonProperty<IfStmt, Block>(json, "ifBody"); | ||||
|   auto elseBody = fromJsonProperty<IfStmt, Block>(json, "elseBody"); | ||||
|   return new IfStmt(SourceRange::json(), std::move(condition), | ||||
|                     std::move(ifBody), std::move(elseBody)); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value RetStmt::toJson() { | ||||
| boost::json::value RetStmt::toJson() const { | ||||
|   return { | ||||
|       {"@type", "RetStmt"}, | ||||
|       {"value", value->toJson()}, | ||||
| @ -12,7 +12,7 @@ boost::json::value RetStmt::toJson() { | ||||
| 
 | ||||
| RetStmt *RetStmt::fromJson(boost::json::value json) { | ||||
|   auto value = fromJsonProperty<RetStmt, Expr>(json, "value"); | ||||
|   return new RetStmt(SourceRange::json(), value); | ||||
|   return new RetStmt(SourceRange::json(), std::move(value)); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value VarDecl::toJson() { | ||||
| boost::json::value VarDecl::toJson() const { | ||||
|   return { | ||||
|       {"@type", "VarDecl"}, | ||||
|       {"name", name}, | ||||
| @ -14,7 +14,7 @@ boost::json::value VarDecl::toJson() { | ||||
| VarDecl *VarDecl::fromJson(boost::json::value json) { | ||||
|   auto name = getJsonValue<VarDecl, std::string>(json, "name"); | ||||
|   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
 | ||||
|  | ||||
| @ -4,18 +4,19 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value WhileStmt::toJson() { | ||||
| boost::json::value WhileStmt::toJson() const { | ||||
|   return { | ||||
|       {"@type", "WhileStmt"}, | ||||
|       {"condition", condition->toJson()}, | ||||
|       {"body", utils::mapToJson(body)}, | ||||
|       {"body", body->toJson()}, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| WhileStmt *WhileStmt::fromJson(boost::json::value json) { | ||||
|   auto condition = fromJsonProperty<WhileStmt, Expr>(json, "condition"); | ||||
|   auto body = fromJsonVector<WhileStmt, Stmt>(json, "body"); | ||||
|   return new WhileStmt(SourceRange::json(), condition, body); | ||||
|   auto body = fromJsonProperty<WhileStmt, Block>(json, "body"); | ||||
|   return new WhileStmt(SourceRange::json(), std::move(condition), | ||||
|                        std::move(body)); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -1,10 +1,13 @@ | ||||
| #include "AST/Type/FunctionType.h" | ||||
| #include "AST/AST.h" | ||||
| #include "AST/Base.h" | ||||
| #include "Utils.h" | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value FunctionType::toJson() { | ||||
| boost::json::value FunctionType::toJson() const { | ||||
|   return { | ||||
|       {"@type", "FunctionType"}, | ||||
|       {"paramTypes", utils::mapToJson(paramTypes)}, | ||||
| @ -13,10 +16,19 @@ boost::json::value FunctionType::toJson() { | ||||
| } | ||||
| 
 | ||||
| FunctionType *FunctionType::fromJson(boost::json::value json) { | ||||
|   auto paramTypes = fromJsonVector<FunctionType, Type>(json, "paramTypes"); | ||||
|   auto returnType = fromJsonProperty<FunctionType, Type>(json, "returnType"); | ||||
|   auto paramTypesU = fromJsonVector<FunctionType, Type>(json, "paramTypes"); | ||||
|   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); | ||||
| } | ||||
| 
 | ||||
| TypeName *FunctionType::toTypeName() { return nullptr; } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
| } // namespace plsm
 | ||||
| @ -1,9 +1,12 @@ | ||||
| #include "AST/AST.h" | ||||
| #include "AST/Base.h" | ||||
| #include "AST/TypeName/NamedTypeName.h" | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value PrimitiveType::toJson() { | ||||
| boost::json::value PrimitiveType::toJson() const { | ||||
|   return { | ||||
|       {"@type", "PrimitiveType"}, | ||||
|       {"name", name}, | ||||
| @ -15,5 +18,9 @@ PrimitiveType *PrimitiveType::fromJson(boost::json::value json) { | ||||
|   return new PrimitiveType(name); | ||||
| } | ||||
| 
 | ||||
| TypeName *PrimitiveType::toTypeName() { | ||||
|   return new NamedTypeName(SourceRange::unknown(), name); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
| } // namespace plsm
 | ||||
| @ -3,13 +3,13 @@ | ||||
| namespace plsm { | ||||
| namespace ast { | ||||
| 
 | ||||
| boost::json::value PrimitiveTypeName::toJson() { | ||||
|   return {{"@type", "PrimitiveTypeName"}, {"name", name}}; | ||||
| boost::json::value NamedTypeName::toJson() const { | ||||
|   return {{"@type", "NamedTypeName"}, {"name", name}}; | ||||
| } | ||||
| 
 | ||||
| PrimitiveTypeName *PrimitiveTypeName::fromJson(boost::json::value json) { | ||||
|   auto name = getJsonValue<PrimitiveTypeName, std::string>(json, "name"); | ||||
|   return new PrimitiveTypeName(SourceRange::json(), name); | ||||
| NamedTypeName *NamedTypeName::fromJson(boost::json::value json) { | ||||
|   auto name = getJsonValue<NamedTypeName, std::string>(json, "name"); | ||||
|   return new NamedTypeName(SourceRange::json(), name); | ||||
| } | ||||
| 
 | ||||
| } // namespace ast
 | ||||
|  | ||||
| @ -1,58 +1,138 @@ | ||||
| #include "AST/BaseASTVisitor.h" | ||||
| #include "Analysis.h" | ||||
| #include "Errors.h" | ||||
| #include "Utils.h" | ||||
| 
 | ||||
| #include <map> | ||||
| #include <stack> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace plsm { | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| 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: | ||||
|   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) {} | ||||
| 
 | ||||
|   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); | ||||
|     fnDecl.symbol = symbol; | ||||
|     scopes->top()[fnDecl.name] = symbol; | ||||
|     scopes->back()[fnDecl.name] = 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->top()[varDecl.name] = symbol; | ||||
|     scopes->back()[varDecl.name] = symbol; | ||||
| 
 | ||||
|     return std::any(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| 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() { | ||||
|     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: | ||||
|   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) {} | ||||
| 
 | ||||
|   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
 | ||||
| 
 | ||||
| void performNameAnalysis(std::shared_ptr<ast::Module> module) { | ||||
|   std::stack<std::map<std::string, std::shared_ptr<ast::Symbol>>> scopes; | ||||
|   scopes.push(std::map<std::string, std::shared_ptr<ast::Symbol>>()); | ||||
| void performNameAnalysis(std::unique_ptr<ast::Module> &module) { | ||||
|   std::vector<std::map<std::string, std::shared_ptr<ast::Symbol>>> scopes; | ||||
|   scopes.push_back(std::map<std::string, std::shared_ptr<ast::Symbol>>()); | ||||
| 
 | ||||
|   NameAnalysisVisitor1 visitor1(&scopes); | ||||
|   NameAnalysisVisitor2 visitor2(&scopes); | ||||
| @ -62,7 +142,8 @@ void performNameAnalysis(std::shared_ptr<ast::Module> module) { | ||||
|   } | ||||
| 
 | ||||
|   for (auto &stmt : module->stmts) { | ||||
|     stmt->accept(&visitor2, nullptr); | ||||
|     if (utils::is<ast::FnDecl>(stmt.get())) | ||||
|       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 "AST/AST.h" | ||||
| #include "Errors.h" | ||||
| #include "plsmBaseVisitor.h" | ||||
| #include "plsmLexer.h" | ||||
| #include "plsmParser.h" | ||||
| 
 | ||||
| namespace plsm { | ||||
| 
 | ||||
| namespace { | ||||
| class MyAntlr4ErrorListener : public antlr4::BaseErrorListener { | ||||
|   std::string file; | ||||
|   std::string *error; | ||||
| 
 | ||||
| public: | ||||
|   MyAntlr4ErrorListener(const std::string &file, std::string *error) | ||||
|       : file(file), error(error) {} | ||||
|   MyAntlr4ErrorListener(const std::string &file) : file(file) {} | ||||
| 
 | ||||
|   virtual void syntaxError(antlr4::Recognizer *recognizer, | ||||
|                            antlr4::Token *offendingSymbol, size_t line, | ||||
|                            size_t charPositionInLine, const std::string &msg, | ||||
|                            std::exception_ptr e) override { | ||||
| 
 | ||||
|     std::stringstream ss; | ||||
|     ss << file << ": line " << line << ":" << charPositionInLine << ": " << msg; | ||||
|     *error = ss.str(); | ||||
|     ss << "In file " << file << ":" << line << ":" << charPositionInLine << "\n" | ||||
|        << terminal::red << msg << terminal::reset; | ||||
| 
 | ||||
|     errors::put(ss.str()); | ||||
|   } | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| 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) { | ||||
|   auto istream = antlr4::ANTLRInputStream(input); | ||||
|   auto lexer = plsmLexer(&istream); | ||||
|   auto tokens = antlr4::CommonTokenStream(&lexer); | ||||
|   auto parser = plsmParser(&tokens); | ||||
|   parser.setFileName(file); | ||||
|   parser.setSourceText(input); | ||||
| 
 | ||||
|   std::string error; | ||||
|   MyAntlr4ErrorListener listener(file, &error); | ||||
|   MyAntlr4ErrorListener listener(file); | ||||
|   parser.removeErrorListeners(); | ||||
|   parser.addErrorListener(&listener); | ||||
| 
 | ||||
|   auto tree = parser.module(); | ||||
|   return std::shared_ptr<Module>(tree->ast); | ||||
|   return std::move(tree->ast); | ||||
| } | ||||
| 
 | ||||
| } // namespace plsm
 | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| #include <sstream> | ||||
| 
 | ||||
| #include "Analysis.h" | ||||
| #include "Errors.h" | ||||
| #include "Parser.h" | ||||
| 
 | ||||
| static std::string readFile(const std::string &path) { | ||||
| @ -25,21 +26,36 @@ int main(int argc, char *argv[]) { | ||||
| 
 | ||||
|   // std::cout << input << std::endl;
 | ||||
| 
 | ||||
|   int exitStatus = EXIT_SUCCESS; | ||||
| 
 | ||||
|   try { | ||||
|     auto module = plsm::parse(argv[1], input); | ||||
|     std::cout << module->toJsonString() << std::endl; | ||||
|     // std::cout << module->toJsonString() << std::endl;
 | ||||
| 
 | ||||
|     plsm::performNameAnalysis(module); | ||||
|     plsm::performTypeAnalysis(module); | ||||
| 
 | ||||
|     // std::cout << "\n\n";
 | ||||
| 
 | ||||
|     // std::cout << plsm::ast::Module::fromJson(module->toJson())->toJson() <<
 | ||||
|     // std::endl;
 | ||||
|   } catch (std::runtime_error &err) { | ||||
|     std::cerr << err.what() << std::endl; | ||||
|     exit(EXIT_FAILURE); | ||||
|     if (strlen(err.what()) > 0) | ||||
|       std::cerr << err.what() << std::endl; | ||||
|     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 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 : int; | ||||
|   asdf = 100; | ||||
| var asdf : i64; | ||||
| 
 | ||||
| fun main(arg0 i64) i8 { | ||||
|   var a : i64; | ||||
|   a = 10 + 2; | ||||
| 
 | ||||
|   if (asdf > 1000) { | ||||
|     a = 1; | ||||
| @ -10,9 +12,5 @@ fun main() i64 { | ||||
|     a = 3; | ||||
|   } | ||||
| 
 | ||||
|   while (a < 10) { | ||||
|     a = a + 1; | ||||
|   } | ||||
| 
 | ||||
|   ret 3 * 10 + 21.0 * 2; | ||||
|   ret 100; | ||||
| } | ||||
|  | ||||
							
								
								
									
										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
	 Ludwig Lehnert
						Ludwig Lehnert