From e35ceeacf97d1f095c78604bb323820450296441 Mon Sep 17 00:00:00 2001 From: Ludwig Lehnert Date: Sun, 22 Dec 2024 01:07:58 +0100 Subject: [PATCH] still revamping... --- compiler/.vscode/settings.json | 3 +- compiler/include/AST/Base.h | 27 +++- compiler/include/AST/BaseASTVisitor.h | 148 ++++++++++++++++++ compiler/include/AST/Expr/BinExpr.h | 2 +- compiler/include/AST/Expr/CallExpr.h | 2 +- compiler/include/AST/Expr/CastExpr.h | 2 +- compiler/include/AST/Expr/Identifier.h | 4 +- compiler/include/AST/Expr/LambdaExpr.h | 2 +- compiler/include/AST/Expr/UnExpr.h | 2 +- compiler/include/AST/Expr/Value.h | 4 +- compiler/include/AST/Module/Import.h | 2 +- compiler/include/AST/Module/Module.h | 2 +- compiler/include/AST/Stmt/AssignStmt.h | 2 +- compiler/include/AST/Stmt/ExprStmt.h | 2 +- compiler/include/AST/Stmt/FnDecl.h | 8 +- compiler/include/AST/Stmt/IfStmt.h | 2 +- compiler/include/AST/Stmt/RetStmt.h | 2 +- compiler/include/AST/Stmt/VarDecl.h | 4 +- compiler/include/AST/Stmt/WhileStmt.h | 2 +- compiler/include/AST/Type/FunctionType.h | 8 +- compiler/include/AST/Type/PrimitiveType.h | 2 +- .../include/AST/TypeName/PrimitiveTypeName.h | 2 +- compiler/include/Analysis.h | 9 ++ compiler/src/Anlaysis/NameAnalysis.cpp | 69 ++++++++ compiler/src/Parser.cpp | 2 + compiler/src/main.cpp | 3 + 26 files changed, 284 insertions(+), 33 deletions(-) create mode 100644 compiler/include/AST/BaseASTVisitor.h create mode 100644 compiler/include/Analysis.h create mode 100644 compiler/src/Anlaysis/NameAnalysis.cpp diff --git a/compiler/.vscode/settings.json b/compiler/.vscode/settings.json index 0da43e9..2930828 100644 --- a/compiler/.vscode/settings.json +++ b/compiler/.vscode/settings.json @@ -79,6 +79,7 @@ "variant": "cpp", "*.inc": "cpp", "source_location": "cpp", - "text_encoding": "cpp" + "text_encoding": "cpp", + "stack": "cpp" } } \ No newline at end of file diff --git a/compiler/include/AST/Base.h b/compiler/include/AST/Base.h index 209c28c..cbd28a2 100644 --- a/compiler/include/AST/Base.h +++ b/compiler/include/AST/Base.h @@ -149,6 +149,23 @@ public: }; }; +class Type : public Jsonable { +public: + Type() : Jsonable() {} + virtual ~Type() = default; + + static Type *fromJson(boost::json::value json); +}; + +class Symbol { + const std::string name; + std::shared_ptr type; + +public: + Symbol(const std::string &name) : name(name) {} + Symbol(const std::string &name, Type *type) : name(name), type(type) {} +}; + class ASTNode : public Jsonable { public: ASTNode(LOC_ARG) : Jsonable(), sourceRange(sourceRange) {} @@ -170,6 +187,8 @@ public: }; class Expr : public ASTNode { + std::shared_ptr type; + public: Expr(LOC_ARG) : ASTNode(sourceRange) {} virtual ~Expr() = default; @@ -199,13 +218,5 @@ public: virtual bool isTypeName() override { return true; } }; -class Type : public Jsonable { -public: - Type() : Jsonable() {} - virtual ~Type() = default; - - static Type *fromJson(boost::json::value json); -}; - } // namespace ast } // namespace plsm diff --git a/compiler/include/AST/BaseASTVisitor.h b/compiler/include/AST/BaseASTVisitor.h new file mode 100644 index 0000000..f5b5b28 --- /dev/null +++ b/compiler/include/AST/BaseASTVisitor.h @@ -0,0 +1,148 @@ +#pragma once + +#include "AST/AST.h" + +namespace plsm { +namespace ast { + +class BaseASTVisitor : public ASTVisitor { +public: + BaseASTVisitor() : ASTVisitor() {}; + + virtual std::any visit(BinExpr &binExpr, std::any param) override { + binExpr.lhs->accept(this, param); + binExpr.rhs->accept(this, param); + return std::any(); + } + + virtual std::any visit(CallExpr &callExpr, std::any param) override { + callExpr.callee->accept(this, param); + + for (auto &arg : callExpr.args) { + 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); + return std::any(); + } + + virtual std::any visit(Identifier &identifier, std::any param) override { + return std::any(); + } + + virtual std::any visit(LambdaExpr &lambdaExpr, std::any param) override { + for (auto ¶m : lambdaExpr.params) { + param->accept(this, param); + } + + for (auto &body : lambdaExpr.body) { + body->accept(this, param); + } + + return std::any(); + } + + virtual std::any visit(UnExpr &unExpr, std::any param) override { + unExpr.expr->accept(this, param); + return std::any(); + } + + virtual std::any visit(IntValue &intValue, std::any param) override { + return std::any(); + } + + virtual std::any visit(FloatValue &floatValue, std::any param) override { + return std::any(); + } + + virtual std::any visit(Import &import, std::any param) override { + return std::any(); + } + + virtual std::any visit(Module &module, std::any param) override { + for (auto &import : module.imports) { + import->accept(this, param); + } + + for (auto &stmt : module.stmts) { + 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); + return std::any(); + } + + virtual std::any visit(ExprStmt &exprStmt, std::any param) override { + exprStmt.expr->accept(this, param); + return std::any(); + } + + virtual std::any visit(FnParam &fnParam, std::any param) override { + 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); + } + + for (auto &body : fnDecl.body) { + 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); + } + + return std::any(); + } + + virtual std::any visit(RetStmt &retStmt, std::any param) override { + retStmt.value->accept(this, param); + return std::any(); + } + + virtual std::any visit(VarDecl &varDecl, std::any param) override { + 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); + } + + return std::any(); + } + + virtual std::any visit(PrimitiveTypeName &primitiveTypeName, + std::any param) override { + return std::any(); + } +}; + +} // namespace ast +} // namespace plsm \ No newline at end of file diff --git a/compiler/include/AST/Expr/BinExpr.h b/compiler/include/AST/Expr/BinExpr.h index 5a36d08..f7e2932 100644 --- a/compiler/include/AST/Expr/BinExpr.h +++ b/compiler/include/AST/Expr/BinExpr.h @@ -26,10 +26,10 @@ enum BinOp { }; class BinExpr : public Expr { +public: const BinOp op; const std::shared_ptr lhs, rhs; -public: BinExpr(LOC_ARG, const BinOp op, Expr *lhs, Expr *rhs) : Expr(sourceRange), op(op), lhs(lhs), rhs(rhs) {} diff --git a/compiler/include/AST/Expr/CallExpr.h b/compiler/include/AST/Expr/CallExpr.h index 5dbdd5a..0043a97 100644 --- a/compiler/include/AST/Expr/CallExpr.h +++ b/compiler/include/AST/Expr/CallExpr.h @@ -8,10 +8,10 @@ namespace plsm { namespace ast { class CallExpr : public Expr { +public: const std::shared_ptr callee; std::vector> args; -public: CallExpr(LOC_ARG, Expr *callee, std::vector args) : Expr(sourceRange), callee(callee), args() { for (auto &arg : args) { diff --git a/compiler/include/AST/Expr/CastExpr.h b/compiler/include/AST/Expr/CastExpr.h index d4224ad..65db20d 100644 --- a/compiler/include/AST/Expr/CastExpr.h +++ b/compiler/include/AST/Expr/CastExpr.h @@ -7,10 +7,10 @@ namespace plsm { namespace ast { class CastExpr : public Expr { +public: const std::shared_ptr value; const std::shared_ptr typeName; -public: CastExpr(LOC_ARG, Expr *value, TypeName *typeName) : Expr(sourceRange), value(value), typeName(typeName) {} diff --git a/compiler/include/AST/Expr/Identifier.h b/compiler/include/AST/Expr/Identifier.h index 451c300..55be875 100644 --- a/compiler/include/AST/Expr/Identifier.h +++ b/compiler/include/AST/Expr/Identifier.h @@ -6,9 +6,11 @@ namespace plsm { namespace ast { class Identifier : public Expr { +public: const std::string name; -public: + std::shared_ptr symbol; + Identifier(LOC_ARG, const std::string &name) : Expr(sourceRange), name(name) {} diff --git a/compiler/include/AST/Expr/LambdaExpr.h b/compiler/include/AST/Expr/LambdaExpr.h index 3d94e95..c09cd3a 100644 --- a/compiler/include/AST/Expr/LambdaExpr.h +++ b/compiler/include/AST/Expr/LambdaExpr.h @@ -10,10 +10,10 @@ namespace ast { class FnParam; class LambdaExpr : public Expr { +public: std::vector> params; std::vector> body; -public: LambdaExpr(LOC_ARG, std::vector params, std::vector body) : Expr(sourceRange), params(), body() { for (auto ¶m : params) { diff --git a/compiler/include/AST/Expr/UnExpr.h b/compiler/include/AST/Expr/UnExpr.h index a415435..ebbe43f 100644 --- a/compiler/include/AST/Expr/UnExpr.h +++ b/compiler/include/AST/Expr/UnExpr.h @@ -13,10 +13,10 @@ enum UnOp { }; class UnExpr : public Expr { +public: const UnOp op; const std::shared_ptr expr; -public: UnExpr(LOC_ARG, const UnOp op, Expr *expr) : Expr(sourceRange), op(op), expr(expr) {} diff --git a/compiler/include/AST/Expr/Value.h b/compiler/include/AST/Expr/Value.h index 81f4b8a..4974264 100644 --- a/compiler/include/AST/Expr/Value.h +++ b/compiler/include/AST/Expr/Value.h @@ -16,9 +16,9 @@ namespace ast { // }; class IntValue : public Expr { +public: const std::int64_t value; -public: IntValue(LOC_ARG, int64_t value) : Expr(sourceRange), value(value) {} virtual boost::json::value toJson() override; @@ -30,9 +30,9 @@ public: }; class FloatValue : public Expr { +public: const std::double_t value; -public: FloatValue(LOC_ARG, double value) : Expr(sourceRange), value(value) {} virtual boost::json::value toJson() override; diff --git a/compiler/include/AST/Module/Import.h b/compiler/include/AST/Module/Import.h index 6ba9014..4499248 100644 --- a/compiler/include/AST/Module/Import.h +++ b/compiler/include/AST/Module/Import.h @@ -6,9 +6,9 @@ namespace plsm { namespace ast { class Import : public ASTNode { +public: const std::string moduleName; -public: Import(LOC_ARG, const std::string &moduleName) : ASTNode(sourceRange), moduleName(moduleName) {} diff --git a/compiler/include/AST/Module/Module.h b/compiler/include/AST/Module/Module.h index c2fd40e..4fadc44 100644 --- a/compiler/include/AST/Module/Module.h +++ b/compiler/include/AST/Module/Module.h @@ -9,11 +9,11 @@ namespace ast { class Import; class Module : public ASTNode { +public: const std::string name; std::vector> imports; std::vector> stmts; -public: Module(LOC_ARG, const std::string &name, const std::vector &imports, const std::vector &stmts) : ASTNode(sourceRange), name(name), imports(), stmts() { diff --git a/compiler/include/AST/Stmt/AssignStmt.h b/compiler/include/AST/Stmt/AssignStmt.h index 560145e..73accb1 100644 --- a/compiler/include/AST/Stmt/AssignStmt.h +++ b/compiler/include/AST/Stmt/AssignStmt.h @@ -8,10 +8,10 @@ namespace plsm { namespace ast { class AssignStmt : public Stmt { +public: const std::shared_ptr lval; const std::shared_ptr rval; -public: AssignStmt(LOC_ARG, Expr *lval, Expr *rval) : Stmt(sourceRange), lval(lval), rval(rval) {} diff --git a/compiler/include/AST/Stmt/ExprStmt.h b/compiler/include/AST/Stmt/ExprStmt.h index 6dfeb55..8864eec 100644 --- a/compiler/include/AST/Stmt/ExprStmt.h +++ b/compiler/include/AST/Stmt/ExprStmt.h @@ -6,9 +6,9 @@ namespace plsm { namespace ast { class ExprStmt : public Stmt { +public: const std::shared_ptr expr; -public: ExprStmt(LOC_ARG, Expr *expr) : Stmt(sourceRange), expr(expr) {} virtual boost::json::value toJson() override; diff --git a/compiler/include/AST/Stmt/FnDecl.h b/compiler/include/AST/Stmt/FnDecl.h index 1ab6c43..52f4399 100644 --- a/compiler/include/AST/Stmt/FnDecl.h +++ b/compiler/include/AST/Stmt/FnDecl.h @@ -9,10 +9,12 @@ namespace plsm { namespace ast { class FnParam : public ASTNode { +public: const std::string name; const std::shared_ptr typeName; -public: + std::shared_ptr symbol; + FnParam(LOC_ARG, const std::string &name, TypeName *typeName) : ASTNode(sourceRange), name(name), typeName(typeName) {} @@ -25,12 +27,14 @@ public: }; class FnDecl : public Stmt { +public: const std::string name; std::vector> params; const std::shared_ptr returnTypeName; std::vector> body; -public: + std::shared_ptr symbol; + FnDecl(LOC_ARG, const std::string &name, const std::vector ¶ms, TypeName *returnTypeName, const std::vector &body) : Stmt(sourceRange), name(name), params(), returnTypeName(returnTypeName), diff --git a/compiler/include/AST/Stmt/IfStmt.h b/compiler/include/AST/Stmt/IfStmt.h index f32400a..262d988 100644 --- a/compiler/include/AST/Stmt/IfStmt.h +++ b/compiler/include/AST/Stmt/IfStmt.h @@ -8,10 +8,10 @@ namespace plsm { namespace ast { class IfStmt : public Stmt { +public: const std::shared_ptr condition; std::vector> ifBody, elseBody; -public: IfStmt(LOC_ARG, Expr *condition, const std::vector &ifBody, const std::vector &elseBody) : Stmt(sourceRange), condition(condition) { diff --git a/compiler/include/AST/Stmt/RetStmt.h b/compiler/include/AST/Stmt/RetStmt.h index b8514d5..1f5becc 100644 --- a/compiler/include/AST/Stmt/RetStmt.h +++ b/compiler/include/AST/Stmt/RetStmt.h @@ -6,9 +6,9 @@ namespace plsm { namespace ast { class RetStmt : public Stmt { +public: const std::shared_ptr value; -public: RetStmt(LOC_ARG, Expr *value) : Stmt(sourceRange), value(value) {} virtual boost::json::value toJson() override; diff --git a/compiler/include/AST/Stmt/VarDecl.h b/compiler/include/AST/Stmt/VarDecl.h index 10c01f8..c0d66d7 100644 --- a/compiler/include/AST/Stmt/VarDecl.h +++ b/compiler/include/AST/Stmt/VarDecl.h @@ -8,10 +8,12 @@ namespace plsm { namespace ast { class VarDecl : public Stmt { +public: const std::string name; const std::shared_ptr typeName; -public: + std::shared_ptr symbol; + VarDecl(LOC_ARG, const std::string &name, TypeName *typeName) : Stmt(sourceRange), name(name), typeName(typeName) {} diff --git a/compiler/include/AST/Stmt/WhileStmt.h b/compiler/include/AST/Stmt/WhileStmt.h index 5b1318d..9c48b7b 100644 --- a/compiler/include/AST/Stmt/WhileStmt.h +++ b/compiler/include/AST/Stmt/WhileStmt.h @@ -7,10 +7,10 @@ namespace plsm { namespace ast { class WhileStmt : public Stmt { +public: const std::shared_ptr condition; std::vector> body; -public: WhileStmt(LOC_ARG, Expr *condition, const std::vector &body) : Stmt(sourceRange), condition(condition) { for (auto &stmt : body) { diff --git a/compiler/include/AST/Type/FunctionType.h b/compiler/include/AST/Type/FunctionType.h index d23c2ab..1cfb077 100644 --- a/compiler/include/AST/Type/FunctionType.h +++ b/compiler/include/AST/Type/FunctionType.h @@ -7,14 +7,14 @@ namespace plsm { namespace ast { class FunctionType : public Type { - std::vector> paramTypes; - const std::unique_ptr returnType; - public: + std::vector> paramTypes; + const std::shared_ptr returnType; + FunctionType(const std::vector ¶mTypes, Type *returnType) : Type(), returnType(returnType) { for (auto ¶mType : paramTypes) { - this->paramTypes.push_back(std::unique_ptr(paramType)); + this->paramTypes.push_back(std::shared_ptr(paramType)); } } diff --git a/compiler/include/AST/Type/PrimitiveType.h b/compiler/include/AST/Type/PrimitiveType.h index ecc10a3..5d40ee5 100644 --- a/compiler/include/AST/Type/PrimitiveType.h +++ b/compiler/include/AST/Type/PrimitiveType.h @@ -6,9 +6,9 @@ namespace plsm { namespace ast { class PrimitiveType : public Type { +public: const std::string name; -public: PrimitiveType(const std::string &name) : Type(), name(name) {} bool operator==(const PrimitiveType &other) { return name == other.name; } diff --git a/compiler/include/AST/TypeName/PrimitiveTypeName.h b/compiler/include/AST/TypeName/PrimitiveTypeName.h index 282557e..aef83dd 100644 --- a/compiler/include/AST/TypeName/PrimitiveTypeName.h +++ b/compiler/include/AST/TypeName/PrimitiveTypeName.h @@ -6,9 +6,9 @@ namespace plsm { namespace ast { class PrimitiveTypeName : public TypeName { +public: const std::string name; -public: PrimitiveTypeName(LOC_ARG, const std::string &name) : TypeName(sourceRange), name(name) {} diff --git a/compiler/include/Analysis.h b/compiler/include/Analysis.h new file mode 100644 index 0000000..0f3333f --- /dev/null +++ b/compiler/include/Analysis.h @@ -0,0 +1,9 @@ +#pragma once + +#include "AST/AST.h" + +namespace plsm { + +void performNameAnalysis(std::shared_ptr module); + +} \ No newline at end of file diff --git a/compiler/src/Anlaysis/NameAnalysis.cpp b/compiler/src/Anlaysis/NameAnalysis.cpp new file mode 100644 index 0000000..34d3784 --- /dev/null +++ b/compiler/src/Anlaysis/NameAnalysis.cpp @@ -0,0 +1,69 @@ +#include "AST/BaseASTVisitor.h" +#include "Analysis.h" + +#include +#include + +namespace plsm { + +namespace { + +class NameAnalysisVisitor1 : public ast::BaseASTVisitor { + std::stack>> *scopes; + +public: + NameAnalysisVisitor1( + std::stack>> *scopes) + : scopes(scopes) {} + + virtual std::any visit(ast::FnDecl &fnDecl, std::any param) override { + auto symbol = std::make_shared(fnDecl.name); + fnDecl.symbol = symbol; + scopes->top()[fnDecl.name] = symbol; + + return std::any(); + } + + virtual std::any visit(ast::VarDecl &varDecl, std::any param) override { + auto symbol = std::make_shared(varDecl.name); + varDecl.symbol = symbol; + scopes->top()[varDecl.name] = symbol; + + return std::any(); + } +}; + +class NameAnalysisVisitor2 : public ast::BaseASTVisitor { + std::stack>> *scopes; + + void push() { + scopes->push(std::map>()); + } + + void pop() { scopes->pop(); } + +public: + NameAnalysisVisitor2( + std::stack>> *scopes) + : scopes(scopes) {} +}; + +} // namespace + +void performNameAnalysis(std::shared_ptr module) { + std::stack>> scopes; + scopes.push(std::map>()); + + NameAnalysisVisitor1 visitor1(&scopes); + NameAnalysisVisitor2 visitor2(&scopes); + + for (auto &stmt : module->stmts) { + stmt->accept(&visitor1, nullptr); + } + + for (auto &stmt : module->stmts) { + stmt->accept(&visitor2, nullptr); + } +} + +} // namespace plsm \ No newline at end of file diff --git a/compiler/src/Parser.cpp b/compiler/src/Parser.cpp index 7f85184..e0e4c81 100644 --- a/compiler/src/Parser.cpp +++ b/compiler/src/Parser.cpp @@ -5,6 +5,7 @@ #include "plsmLexer.h" #include "plsmParser.h" +namespace { class MyAntlr4ErrorListener : public antlr4::BaseErrorListener { std::string file; std::string *error; @@ -22,6 +23,7 @@ public: *error = ss.str(); } }; +} // namespace namespace plsm { diff --git a/compiler/src/main.cpp b/compiler/src/main.cpp index b2d4f45..ed0d693 100644 --- a/compiler/src/main.cpp +++ b/compiler/src/main.cpp @@ -3,6 +3,7 @@ #include #include +#include "Analysis.h" #include "Parser.h" static std::string readFile(const std::string &path) { @@ -28,6 +29,8 @@ int main(int argc, char *argv[]) { auto module = plsm::parse(argv[1], input); std::cout << module->toJsonString() << std::endl; + plsm::performNameAnalysis(module); + // std::cout << "\n\n"; // std::cout << plsm::ast::Module::fromJson(module->toJson())->toJson() <<