From 34160a03afecbf30dfec6137caf7f50c1298751b Mon Sep 17 00:00:00 2001 From: Ludwig Lehnert Date: Fri, 1 Mar 2024 07:06:51 +0100 Subject: [PATCH] extended ANTLR visitor; added llvm-project --- .gitmodules | 3 + compiler/.gitignore | 3 + compiler/CMakeLists.txt | 2 + compiler/include/AST/Base.h | 24 ++ compiler/include/AST/Def.h | 4 +- compiler/include/AST/Expr/BinExpr.h | 25 +- compiler/include/AST/Expr/Block.h | 24 +- compiler/include/AST/Expr/Call.h | 25 +- compiler/include/AST/Expr/Closure.h | 23 +- compiler/include/AST/Expr/Identifier.h | 8 +- compiler/include/AST/Expr/PropExpr.h | 27 ++ compiler/include/AST/Expr/Tuple.h | 17 + compiler/include/AST/Expr/UnaryExpr.h | 4 +- compiler/include/AST/Expr/Value.h | 12 +- compiler/include/AST/Module/Import.h | 3 +- compiler/include/AST/Module/Module.h | 5 +- compiler/include/AST/Stmt/ExprStmt.h | 3 +- compiler/include/AST/Stmt/FnDecl.h | 23 - compiler/include/AST/Stmt/FnDef.h | 31 ++ compiler/include/AST/Stmt/TraitAlias.h | 4 +- compiler/include/AST/Stmt/TraitDef.h | 8 +- compiler/include/AST/Stmt/TypeAlias.h | 4 +- compiler/include/AST/Stmt/TypeDef.h | 13 +- compiler/include/AST/Stmt/ValDecl.h | 4 +- compiler/include/AST/Type/Closure.h | 4 +- compiler/include/AST/Type/Generic.h | 4 +- compiler/include/AST/Type/Named.h | 3 +- compiler/include/AST/Type/Tuple.h | 4 +- compiler/include/Parser.h | 4 +- compiler/plsm.g4 | 40 +- compiler/setup/llvm | 17 + compiler/src/Parser.cpp | 574 ++++++++++++++++++++----- compiler/src/main.cpp | 30 +- compiler/thirdparty/llvm-project | 1 + examples/42.plsm | 6 +- 35 files changed, 794 insertions(+), 192 deletions(-) create mode 100644 .gitmodules create mode 100644 compiler/include/AST/Expr/PropExpr.h create mode 100644 compiler/include/AST/Expr/Tuple.h delete mode 100644 compiler/include/AST/Stmt/FnDecl.h create mode 100644 compiler/include/AST/Stmt/FnDef.h create mode 100755 compiler/setup/llvm create mode 160000 compiler/thirdparty/llvm-project diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0aebb05 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "compiler/thirdparty/llvm-project"] + path = compiler/thirdparty/llvm-project + url = https://github.com/llvm/llvm-project.git diff --git a/compiler/.gitignore b/compiler/.gitignore index 2a03c28..d6f6c8e 100644 --- a/compiler/.gitignore +++ b/compiler/.gitignore @@ -6,3 +6,6 @@ # antlr-generated files plsm*.h plsm*.cpp + +# coredumps +vgcore.* diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index 2da6d53..b24aab9 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.25) project(plasmatum) +set(CMAKE_BUILD_TYPE Debug) + set(CMAKE_CXX_STANDARD 23) set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) set(INC_DIR ${CMAKE_SOURCE_DIR}/include) diff --git a/compiler/include/AST/Base.h b/compiler/include/AST/Base.h index 991c6ab..d2027ab 100644 --- a/compiler/include/AST/Base.h +++ b/compiler/include/AST/Base.h @@ -1,12 +1,33 @@ #pragma once +#include +#include +#include + +#define LOC_ARG const Location &location + namespace ast { + class Location + { + public: + Location(const std::string &file, std::pair start, std::pair end) + : file(file), start(start), end(end) {} + + const std::string file; + const std::pair start, end; + }; + class ASTNode { public: + ASTNode(LOC_ARG) : location(location) {} virtual ~ASTNode() = default; + const Location location; + + virtual std::string str() = 0; + virtual bool isExpr() { return false; } virtual bool isStmt() { return false; } virtual bool isType() { return false; } @@ -15,18 +36,21 @@ namespace ast class Expr : public ASTNode { public: + Expr(LOC_ARG) : ASTNode(location) {} virtual bool isExpr() override { return true; } }; class Stmt : public ASTNode { public: + Stmt(LOC_ARG) : ASTNode(location) {} virtual bool isStmt() override { return true; } }; class Type : public ASTNode { public: + Type(LOC_ARG) : ASTNode(location) {} virtual bool isType() override { return true; } }; } \ No newline at end of file diff --git a/compiler/include/AST/Def.h b/compiler/include/AST/Def.h index 8b323a0..c0e2da4 100644 --- a/compiler/include/AST/Def.h +++ b/compiler/include/AST/Def.h @@ -7,11 +7,13 @@ #include "Expr/Call.h" #include "Expr/Closure.h" #include "Expr/Identifier.h" +#include "Expr/PropExpr.h" +#include "Expr/Tuple.h" #include "Expr/UnaryExpr.h" #include "Expr/Value.h" #include "Stmt/ExprStmt.h" -#include "Stmt/FnDecl.h" +#include "Stmt/FnDef.h" #include "Stmt/TraitAlias.h" #include "Stmt/TraitDef.h" #include "Stmt/TypeAlias.h" diff --git a/compiler/include/AST/Expr/BinExpr.h b/compiler/include/AST/Expr/BinExpr.h index 4f7fc7c..0a298d7 100644 --- a/compiler/include/AST/Expr/BinExpr.h +++ b/compiler/include/AST/Expr/BinExpr.h @@ -12,8 +12,18 @@ namespace ast const std::unique_ptr left, right; public: - BinExpr(std::unique_ptr &left, const std::string &op, std::unique_ptr &right) - : left(std::move(left)), op(op), right(std::move(right)) {} + BinExpr(LOC_ARG, std::unique_ptr &left, const std::string &op, std::unique_ptr &right) + : Expr(location), left(std::move(left)), op(op), right(std::move(right)) {} + + virtual std::string str(size_t indent, size_t tabstop) + { + return (std::stringstream() << "BinExpr(" + << "op=\"" << op << "\", " + << "left=" << left->str() << ", " + << "right=" << right->str() + << ")") + .str(); + } }; class PrefExpr : public Expr @@ -21,6 +31,15 @@ namespace ast const std::unique_ptr expr; public: - PrefExpr(std::unique_ptr &expr) : expr(std::move(expr)) {} + PrefExpr(LOC_ARG, std::unique_ptr &expr) + : Expr(location), expr(std::move(expr)) {} + + virtual std::string str() + { + return (std::stringstream() << "PrefExpr(" + << "expr=" << expr->str() + << ")") + .str(); + } }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Block.h b/compiler/include/AST/Expr/Block.h index 37852da..7f230ad 100644 --- a/compiler/include/AST/Expr/Block.h +++ b/compiler/include/AST/Expr/Block.h @@ -9,8 +9,30 @@ namespace ast class BlockExpr : public Expr { const std::vector> stmts; + const std::unique_ptr result; public: - BlockExpr(std::vector> &stmts) : stmts(std::move(stmts)) {} + BlockExpr(LOC_ARG, std::vector> &stmts, std::unique_ptr &result) + : Expr(location), stmts(std::move(stmts)), result(std::move(result)) {} + + virtual std::string str() + { + std::stringstream ss; + ss << "BlockExpr("; + + ss << "stmts=["; + for (size_t i = 0; i < stmts.size(); i++) + { + ss << stmts[i]->str(); + if (i != stmts.size() - 1) + ss << ", "; + } + ss << "], "; + + ss << "result=" << result->str(); + ss << ")"; + + return ss.str(); + } }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Call.h b/compiler/include/AST/Expr/Call.h index 07f81bb..dbdad9a 100644 --- a/compiler/include/AST/Expr/Call.h +++ b/compiler/include/AST/Expr/Call.h @@ -12,7 +12,28 @@ namespace ast const std::vector> args; public: - CallExpr(std::unique_ptr &callee, std::vector> &args) - : callee(std::move(callee)), args(std::move(args)) {} + CallExpr(LOC_ARG, std::unique_ptr &callee, std::vector> &args) + : Expr(location), callee(std::move(callee)), args(std::move(args)) {} + + virtual std::string str() + { + std::stringstream ss; + + ss << "CallExpr("; + ss << "callee=" << callee->str(); + + ss << "args=["; + for (size_t i = 0; i < args.size(); i++) + { + ss << args[i]->str(); + if (i != args.size() - 1) + ss << ", "; + } + ss << "]"; + + ss << ")"; + + return ss.str(); + } }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Closure.h b/compiler/include/AST/Expr/Closure.h index 2f9122c..84b0af1 100644 --- a/compiler/include/AST/Expr/Closure.h +++ b/compiler/include/AST/Expr/Closure.h @@ -13,7 +13,26 @@ namespace ast const std::unique_ptr body; public: - Closure(std::vector &args, std::unique_ptr &body) - : args(std::move(args)), body(std::move(body)) {} + Closure(LOC_ARG, std::vector &args, std::unique_ptr &body) + : Expr(location), args(std::move(args)), body(std::move(body)) {} + + virtual std::string str() + { + std::stringstream ss; + + ss << "CallExpr("; + ss << "args=["; + for (size_t i = 0; i < args.size(); i++) + { + ss << args[i]; + if (i != args.size() - 1) + ss << ", "; + } + ss << "], "; + ss << "body=" << body->str(); + ss << ")"; + + return ss.str(); + } }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Identifier.h b/compiler/include/AST/Expr/Identifier.h index a3a7343..a9d5236 100644 --- a/compiler/include/AST/Expr/Identifier.h +++ b/compiler/include/AST/Expr/Identifier.h @@ -10,6 +10,12 @@ namespace ast const std::string name; public: - Identifier(const std::string &name) : name(name) {} + Identifier(LOC_ARG, const std::string &name) + : Expr(location), name(name) {} + + virtual std::string str() + { + return "Identifier(" + name + ")"; + } }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/PropExpr.h b/compiler/include/AST/Expr/PropExpr.h new file mode 100644 index 0000000..ad837ab --- /dev/null +++ b/compiler/include/AST/Expr/PropExpr.h @@ -0,0 +1,27 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class PropExpr : public Expr + { + const std::unique_ptr expr; + const std::string property; + + public: + PropExpr(LOC_ARG, std::unique_ptr &expr, const std::string &property) + : Expr(location), expr(std::move(expr)), property(property) {} + + virtual std::string str() + { + return (std::stringstream() << "PropExpr(" + << "expr=" << expr->str() << ", " + << "property=" << property + << ")") + .str(); + } + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Expr/Tuple.h b/compiler/include/AST/Expr/Tuple.h new file mode 100644 index 0000000..9857937 --- /dev/null +++ b/compiler/include/AST/Expr/Tuple.h @@ -0,0 +1,17 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class Tuple : public Expr + { + const std::vector> values; + + public: + Tuple(LOC_ARG, std::vector> &values) + : Expr(location), values(std::move(values)) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Expr/UnaryExpr.h b/compiler/include/AST/Expr/UnaryExpr.h index 2dbf1f8..5d67466 100644 --- a/compiler/include/AST/Expr/UnaryExpr.h +++ b/compiler/include/AST/Expr/UnaryExpr.h @@ -12,7 +12,7 @@ namespace ast const std::unique_ptr expr; public: - UnaryExpr(const std::string &op, std::unique_ptr &expr) - : op(op), expr(std::move(expr)) {} + UnaryExpr(LOC_ARG, const std::string &op, std::unique_ptr &expr) + : Expr(location), op(op), expr(std::move(expr)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Value.h b/compiler/include/AST/Expr/Value.h index a758e24..44acb0f 100644 --- a/compiler/include/AST/Expr/Value.h +++ b/compiler/include/AST/Expr/Value.h @@ -5,12 +5,19 @@ namespace ast { + class NullValue : public Expr + { + public: + NullValue(LOC_ARG) : Expr(location) {} + }; + class IntValue : public Expr { const int64_t value; public: - IntValue(int64_t value) : value(value) {} + IntValue(LOC_ARG, int64_t value) + : Expr(location), value(value) {} }; class FloatValue : public Expr @@ -18,6 +25,7 @@ namespace ast const double value; public: - FloatValue(double value) : value(value) {} + FloatValue(LOC_ARG, double value) + : Expr(location), value(value) {} }; } diff --git a/compiler/include/AST/Module/Import.h b/compiler/include/AST/Module/Import.h index f3acd06..fc974a2 100644 --- a/compiler/include/AST/Module/Import.h +++ b/compiler/include/AST/Module/Import.h @@ -10,6 +10,7 @@ namespace ast const std::string moduleName; public: - Import(const std::string &moduleName) : moduleName(moduleName) {} + Import(LOC_ARG, const std::string &moduleName) + : ASTNode(location), moduleName(moduleName) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Module/Module.h b/compiler/include/AST/Module/Module.h index 8d0d0b5..51bbe67 100644 --- a/compiler/include/AST/Module/Module.h +++ b/compiler/include/AST/Module/Module.h @@ -10,11 +10,12 @@ namespace ast class Module : public ASTNode { + const std::string name; const std::vector> imports; const std::vector> stmts; public: - Module(std::vector> &imports, std::vector> &stmts) - : imports(std::move(imports)), stmts(std::move(stmts)) {} + Module(LOC_ARG, const std::string &name, std::vector> &imports, std::vector> &stmts) + : ASTNode(location), name(name), imports(std::move(imports)), stmts(std::move(stmts)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/ExprStmt.h b/compiler/include/AST/Stmt/ExprStmt.h index 7160349..df31979 100644 --- a/compiler/include/AST/Stmt/ExprStmt.h +++ b/compiler/include/AST/Stmt/ExprStmt.h @@ -10,6 +10,7 @@ namespace ast const std::unique_ptr expr; public: - ExprStmt(std::unique_ptr &expr) : expr(std::move(expr)) {} + ExprStmt(LOC_ARG, std::unique_ptr &expr) + : Stmt(location), expr(std::move(expr)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/FnDecl.h b/compiler/include/AST/Stmt/FnDecl.h deleted file mode 100644 index bb05ea3..0000000 --- a/compiler/include/AST/Stmt/FnDecl.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "AST/Base.h" -#include -#include -#include - -namespace ast -{ - typedef std::pair> FnArg; - - class FnDecl : public Stmt - { - const std::string name; - const std::vector args; - const std::unique_ptr returnType; - const std::unique_ptr body; - - public: - FnDecl(const std::string &name, std::vector &args, std::unique_ptr &returnType, std::unique_ptr &body) - : name(name), args(std::move(args)), returnType(std::move(returnType)), body(std::move(body)) {} - }; -} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/FnDef.h b/compiler/include/AST/Stmt/FnDef.h new file mode 100644 index 0000000..f2d241f --- /dev/null +++ b/compiler/include/AST/Stmt/FnDef.h @@ -0,0 +1,31 @@ +#pragma once + +#include "AST/Base.h" +#include +#include +#include + +namespace ast +{ + class FnArg : public ASTNode + { + const std::string name; + const std::unique_ptr type; + + public: + FnArg(LOC_ARG, const std::string &name, std::unique_ptr &type) + : ASTNode(location), name(name), type(std::move(type)) {} + }; + + class FnDef : public Stmt + { + const std::string name; + const std::vector> args; + const std::unique_ptr returnType; + const std::unique_ptr body; + + public: + FnDef(LOC_ARG, const std::string &name, std::vector> &args, std::unique_ptr &returnType, std::unique_ptr &body) + : Stmt(location), name(name), args(std::move(args)), returnType(std::move(returnType)), body(std::move(body)) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TraitAlias.h b/compiler/include/AST/Stmt/TraitAlias.h index 4de89ab..3185f7c 100644 --- a/compiler/include/AST/Stmt/TraitAlias.h +++ b/compiler/include/AST/Stmt/TraitAlias.h @@ -13,7 +13,7 @@ namespace ast const std::string aliased; public: - TraitAlias(const std::string &alias, const std::string &aliased) - : alias(alias), aliased(aliased) {} + TraitAlias(LOC_ARG, const std::string &alias, const std::string &aliased) + : Stmt(location), alias(alias), aliased(aliased) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TraitDef.h b/compiler/include/AST/Stmt/TraitDef.h index cd01e06..bab027a 100644 --- a/compiler/include/AST/Stmt/TraitDef.h +++ b/compiler/include/AST/Stmt/TraitDef.h @@ -7,15 +7,15 @@ namespace ast { - class FnDecl; + class FnDef; class TraitDef : public Stmt { const std::string name; - const std::vector> traits; + const std::vector> traits; public: - TraitDef(const std::string &name, std::vector> &traits) - : name(name), traits(std::move(traits)) {} + TraitDef(LOC_ARG, const std::string &name, std::vector> &traits) + : Stmt(location), name(name), traits(std::move(traits)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TypeAlias.h b/compiler/include/AST/Stmt/TypeAlias.h index 6dfe87c..b7b9c96 100644 --- a/compiler/include/AST/Stmt/TypeAlias.h +++ b/compiler/include/AST/Stmt/TypeAlias.h @@ -13,7 +13,7 @@ namespace ast const std::unique_ptr type; public: - TypeAlias(const std::string &alias, std::unique_ptr &type) - : alias(alias), type(std::move(type)) {} + TypeAlias(LOC_ARG, const std::string &alias, std::unique_ptr &type) + : Stmt(location), alias(alias), type(std::move(type)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TypeDef.h b/compiler/include/AST/Stmt/TypeDef.h index 736e27f..b008b56 100644 --- a/compiler/include/AST/Stmt/TypeDef.h +++ b/compiler/include/AST/Stmt/TypeDef.h @@ -7,18 +7,17 @@ namespace ast { - class FnDecl; - - typedef std::pair> TypeAttr; + class FnDef; + class FnArg; class TypeDef : public Stmt { const std::string name; - const std::vector attrs; - const std::vector> members; + const std::vector> attrs; + const std::vector> members; public: - TypeDef(const std::string &name, std::vector &attrs, std::vector> &members) - : name(name), attrs(std::move(attrs)), members(std::move(members)) {} + TypeDef(LOC_ARG, const std::string &name, std::vector> &attrs, std::vector> &members) + : Stmt(location), name(name), attrs(std::move(attrs)), members(std::move(members)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/ValDecl.h b/compiler/include/AST/Stmt/ValDecl.h index 22039fd..9f3dc20 100644 --- a/compiler/include/AST/Stmt/ValDecl.h +++ b/compiler/include/AST/Stmt/ValDecl.h @@ -13,7 +13,7 @@ namespace ast const std::unique_ptr value; public: - ValDecl(const std::string &name, std::unique_ptr &type, std::unique_ptr &value) - : name(name), type(std::move(type)), value(std::move(value)) {} + ValDecl(LOC_ARG, const std::string &name, std::unique_ptr &type, std::unique_ptr &value) + : Stmt(location), name(name), type(std::move(type)), value(std::move(value)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Type/Closure.h b/compiler/include/AST/Type/Closure.h index 7565d37..db15d1e 100644 --- a/compiler/include/AST/Type/Closure.h +++ b/compiler/include/AST/Type/Closure.h @@ -12,7 +12,7 @@ namespace ast const std::unique_ptr to; public: - ClosureType(std::vector> &from, std::unique_ptr &to) - : from(std::move(from)), to(std::move(to)) {} + ClosureType(LOC_ARG, std::vector> &from, std::unique_ptr &to) + : Type(location), from(std::move(from)), to(std::move(to)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Type/Generic.h b/compiler/include/AST/Type/Generic.h index df5811c..bb47146 100644 --- a/compiler/include/AST/Type/Generic.h +++ b/compiler/include/AST/Type/Generic.h @@ -13,7 +13,7 @@ namespace ast const std::vector> types; public: - GenericType(const std::string &name, std::vector> &types) - : name(name), types(std::move(types)) {} + GenericType(LOC_ARG, const std::string &name, std::vector> &types) + : Type(location), name(name), types(std::move(types)) {} }; } diff --git a/compiler/include/AST/Type/Named.h b/compiler/include/AST/Type/Named.h index 9c0cdd0..de3c73d 100644 --- a/compiler/include/AST/Type/Named.h +++ b/compiler/include/AST/Type/Named.h @@ -10,6 +10,7 @@ namespace ast const std::string name; public: - NamedType(const std::string &name) : name(name) {} + NamedType(LOC_ARG, const std::string &name) + : Type(location), name(name) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Type/Tuple.h b/compiler/include/AST/Type/Tuple.h index b8a6595..68accfc 100644 --- a/compiler/include/AST/Type/Tuple.h +++ b/compiler/include/AST/Type/Tuple.h @@ -11,7 +11,7 @@ namespace ast const std::vector> types; public: - TupleType(std::vector> &types) - : types(std::move(types)) {} + TupleType(LOC_ARG, std::vector> &types) + : Type(location), types(std::move(types)) {} }; } \ No newline at end of file diff --git a/compiler/include/Parser.h b/compiler/include/Parser.h index cef89b2..833a659 100644 --- a/compiler/include/Parser.h +++ b/compiler/include/Parser.h @@ -9,10 +9,10 @@ namespace plsm { - std::unique_ptr parse(const std::string &input); + std::unique_ptr parse(const std::string &file, const std::string &input); } namespace adscript { - std::unique_ptr parse(const std::string &input); + std::unique_ptr parse(const std::string &file, const std::string &input); } diff --git a/compiler/plsm.g4 b/compiler/plsm.g4 index 7c39214..a999b73 100644 --- a/compiler/plsm.g4 +++ b/compiler/plsm.g4 @@ -1,9 +1,10 @@ grammar plsm; -module: moduleImport* (let | fnDecl | fnDef | traitDef | typeDef)*; +module: MODULE identifier ';' moduleImport* moduleStmt*; -moduleImport: IMPORT moduleName ';'; -moduleName: identifier ('.' identifier)*; +moduleImport: IMPORT importName ';'; +importName: identifier ('/' identifier)*; +moduleStmt: let | fnDecl | fnDef | traitDef | typeDef; traitDef: TRAIT identifier '=' identifier ';' | TRAIT identifier '=' '{' (fnDecl)* '}' ';'; @@ -21,44 +22,46 @@ let: LET identifier type? '=' expr ';'; exprStmt: expr ';'; -type: type2; -type2: type1 +type: type1; // novisit +type1: type0 | '(' type ')' | '(' tupleTypeList ')' // tuple | '[' typeList? ']' '->' type; // closure -type1: type0 - | type0 '{' typeList '}'; // generic -type0: identifier; +type0: identifier + | identifier '{' typeList '}'; // generic -tupleTypeList: type ',' type (',' type)*; +tupleTypeList: type (',' type)+; typeList: type (',' type)*; -expr: expr3; +expr: expr3; // novisit expr3: expr2 | '[' identifierList? ']' '->' expr // closure - | '{' (let | exprStmt | fnDef)* (expr ';') '}'; + | '{' blockStmt* (expr ';') '}'; expr2: expr1 - | expr2 operator expr1; // binary expr + | expr2 operator expr1; // binary expr expr1: expr0 - | operator expr0; // unary expr + | operator expr0; // unary expr expr0: literal | identifier - | expr0 '[' exprList? ']' // fn call + | expr0 '[' exprList? ']' // fn call | '(' expr ')' - | expr0 '.' identifier; // property accessor + | '(' tupleExprList ')' // tuple + | expr0 '.' identifier; // property accessor +blockStmt: let | exprStmt | fnDef; +tupleExprList: expr (',' expr)+; exprList: expr (',' expr)*; identifierList: identifier (',' identifier)*; -literal: 'null' | INT_LIT | FLOAT_LIT; +literal: NULL='null' | INT_LIT | FLOAT_LIT; operator: '=' | '->' | OPERATOR; identifier: keyword | IDENTIFIER; -keyword: BINOP | FN | IMPORT | LET | NATIVE | TRAIT | TYPE | UNOP; +keyword: BINOP | FN | IMPORT | LET | MODULE | NATIVE | TRAIT | TYPE | UNOP; INT_LIT: [0-9]+ | '0x' [0-9a-fA-F]+ | '0o' [0-7]+ | '0b' [01]+; @@ -70,9 +73,12 @@ BINOP: 'binop'; FN: 'fn'; IMPORT: 'import'; LET: 'let'; +MODULE: 'module'; NATIVE: 'native'; TRAIT: 'trait'; TYPE: 'type'; UNOP: 'unop'; IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; + +WHITESPACE: [ \r\n\t]+ -> skip; diff --git a/compiler/setup/llvm b/compiler/setup/llvm new file mode 100755 index 0000000..a4f2b10 --- /dev/null +++ b/compiler/setup/llvm @@ -0,0 +1,17 @@ +#!/usr/bin/bash + +BASEDIR=$(dirname $(realpath "$0")) + +cd "$BASEDIR/../compiler/thirdparty/llvm-project" + +mkdir -p build +cd build + +cmake -G Ninja ../llvm \ + -DLLVM_ENABLE_PROJECTS="mlir;llvm;lld" \ + -DLLVM_BUILD_EXAMPLES=ON \ + -DLLVM_TARGETS_TO_BUILD="Native;NVPTX;AMDGPU" \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_ASSERTIONS=ON + +cmake --build . diff --git a/compiler/src/Parser.cpp b/compiler/src/Parser.cpp index d7c7bc4..ea8ead7 100644 --- a/compiler/src/Parser.cpp +++ b/compiler/src/Parser.cpp @@ -4,128 +4,502 @@ #include -class Visitor : public plsmBaseVisitor -{ -public: - Visitor() {} - - template - inline T visitT(antlr4::tree::ParseTree *ctx) - { - return std::any_cast(visit(ctx)); - } - - template - inline std::unique_ptr visitU(antlr4::tree::ParseTree *ctx) - { - return std::unique_ptr(visitT(ctx)); - } - - virtual std::any visitModule(plsmParser::ModuleContext *ctx) override - { - std::vector> imports; - std::vector> stmts; - - for (auto &child : ctx->children) - { - if (plsmParser::ModuleImportContext *c = dynamic_cast(child)) - imports.push_back(visitU(child)); - else - stmts.push_back(visitU(child)); - } - - return std::any(new ast::Module(imports, stmts)); - } - - virtual std::any visitModuleImport(plsmParser::ModuleImportContext *ctx) override - { - return std::any(new ast::Import(visitT(ctx->moduleName()))); - } - - virtual std::any visitModuleName(plsmParser::ModuleNameContext *ctx) override - { - auto name = visitT(ctx->identifier(0)); - - for (size_t i = 1; ctx->identifier(i); i++) - { - name = name + "." + visitT(ctx->identifier(i)); - } - - return std::any(name); - } - - virtual std::any visitTraitDef(plsmParser::TraitDefContext *ctx) override - { - auto name = visitT(ctx->identifier(0)); - - if (ctx->identifier(1)) - { - auto aliased = visitT(ctx->identifier(1)); - return std::any(new ast::TraitAlias(name, aliased)); - } - - std::vector> fns; - - for (size_t i = 0; ctx->fnDecl(i); i++) - fns.push_back(visitU(ctx->fnDecl(i))); - - return std::any(new ast::TraitDef(name, fns)); - } - - virtual std::any visitTypeDef(plsmParser::TypeDefContext *ctx) override - { - auto name = visitT(ctx->identifier()); - - if (ctx->type()) - { - auto gen = visitU(ctx->type()); - return std::any(new ast::TypeAlias(name, gen)); - } - - std::vector args; - } -}; - class ErrorListener : public antlr4::BaseErrorListener { + std::string file; std::string *error; public: - ErrorListener(std::string *error) : error(error) {} + ErrorListener(const std::string &file, std::string *error) + : file(file), error(error) {} virtual void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, size_t charPositionInLine, const std::string &msg, std::exception_ptr e) override { std::stringstream ss; - ss << "line " << line << ":" << charPositionInLine << ": " << msg; + ss << file << ": line " << line << ":" << charPositionInLine << ": " << msg; *error = ss.str(); } }; -std::unique_ptr -plsm::parse(const std::string &input) +namespace plsm { - auto istream = antlr4::ANTLRInputStream(input); - auto lexer = plsmLexer(&istream); - auto tokens = antlr4::CommonTokenStream(&lexer); - auto parser = plsmParser(&tokens); + class Visitor : public plsmBaseVisitor + { + private: + const std::string file; - std::string error; - ErrorListener listener(&error); - parser.removeErrorListeners(); - parser.addErrorListener(&listener); + public: + Visitor(const std::string &file) : file(file) {} - auto tree = parser.module(); + inline ast::Location loc(antlr4::ParserRuleContext *ctx) + { + return ast::Location( + file, + std::pair( + ctx->getStart()->getLine(), + ctx->getStart()->getCharPositionInLine()), + std::pair( + ctx->getStop()->getLine(), + ctx->getStop()->getCharPositionInLine())); + } - if (error.size()) - throw std::runtime_error(error); + template + inline T visitT(antlr4::tree::ParseTree *ctx) + { + return std::any_cast(visit(ctx)); + } - auto module = std::any_cast(Visitor().visitModule(tree)); - return std::unique_ptr(module); + template + inline std::unique_ptr visitU(antlr4::tree::ParseTree *ctx) + { + return std::unique_ptr(visitT(ctx)); + } + + template + inline std::vector> visitVU(antlr4::tree::ParseTree *ctx) + { + std::vector> res; + for (auto &el : visitT>(ctx)) + res.push_back(std::unique_ptr(el)); + return res; + } + + virtual std::any visitModule(plsmParser::ModuleContext *ctx) override + { + auto name = ctx->identifier()->getText(); + + std::vector> imports; + for (auto &import : ctx->moduleImport()) + imports.push_back(visitU(import)); + + std::vector> stmts; + for (auto &stmt : ctx->moduleStmt()) + stmts.push_back(visitU(stmt)); + + return std::any(new ast::Module(loc(ctx), name, imports, stmts)); + } + + virtual std::any visitModuleImport(plsmParser::ModuleImportContext *ctx) override + { + return std::any(new ast::Import(loc(ctx), visitT(ctx->importName()))); + } + + virtual std::any visitImportName(plsmParser::ImportNameContext *ctx) override + { + auto name = ctx->identifier(0)->getText(); + + for (size_t i = 1; i < ctx->identifier().size(); i++) + name = name + "/" + ctx->identifier(i)->getText(); + + return std::any(name); + } + + virtual std::any visitModuleStmt(plsmParser::ModuleStmtContext *ctx) override + { + ast::Stmt *stmt; + + if (ctx->let()) + stmt = (ast::Stmt *)visitT(ctx->let()); + if (ctx->fnDecl()) + stmt = (ast::Stmt *)visitT(ctx->fnDecl()); + if (ctx->fnDef()) + stmt = (ast::Stmt *)visitT(ctx->fnDef()); + if (ctx->traitDef()) + stmt = (ast::Stmt *)visitT(ctx->traitDef()); + if (ctx->typeDef()) + stmt = (ast::Stmt *)visitT(ctx->typeDef()); + + return std::any(stmt); + } + + virtual std::any visitTraitDef(plsmParser::TraitDefContext *ctx) override + { + auto name = ctx->identifier(0)->getText(); + + if (ctx->identifier(1)) + { + auto aliased = ctx->identifier(1)->getText(); + return std::any((ast::Stmt *)new ast::TraitAlias(loc(ctx), name, aliased)); + } + + std::vector> fns; + for (auto &decl : ctx->fnDecl()) + fns.push_back(visitU(decl)); + + return std::any((ast::Stmt *)new ast::TraitDef(loc(ctx), name, fns)); + } + + virtual std::any visitTypeDef(plsmParser::TypeDefContext *ctx) override + { + auto name = ctx->identifier()->getText(); + + if (ctx->type()) + { + auto gen = visitU(ctx->type()); + return std::any((ast::Stmt *)new ast::TypeAlias(loc(ctx), name, gen)); + } + + std::vector> attrs; + if (ctx->fnDefArgs()) + attrs = visitVU(ctx->fnDefArgs()); + + std::vector> members; + for (auto &def : ctx->fnDef()) + members.push_back(visitU(def)); + for (auto &decl : ctx->fnDecl()) + members.push_back(visitU(decl)); + + return std::any((ast::Stmt *)new ast::TypeDef(loc(ctx), name, attrs, members)); + } + + virtual std::any visitFnDef(plsmParser::FnDefContext *ctx) override + { + auto name = ctx->identifier()->getText(); + + std::vector> args; + if (ctx->fnDefArgs()) + args = std::move(visitVU(ctx->fnDefArgs())); + + auto returnType = visitU(ctx->type()); + auto body = visitU(ctx->expr()); + + return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body)); + } + + virtual std::any visitFnDefArgs(plsmParser::FnDefArgsContext *ctx) override + { + std::vector args; + + for (size_t i = 0; i < ctx->children.size(); i += 3) + { + auto name = ctx->children[i]->getText(); + auto type = visitU(ctx->children[i + 1]); + args.push_back(new ast::FnArg(loc(ctx), name, type)); + } + + return std::any(args); + } + + virtual std::any visitFnDecl(plsmParser::FnDeclContext *ctx) override + { + auto name = ctx->identifier()->getText(); + + std::vector> args; + if (ctx->fnDeclArgs()) + args = visitVU(ctx->fnDeclArgs()); + + auto returnType = visitU(ctx->type()); + auto body = std::unique_ptr(nullptr); + + return std::any(new ast::FnDef(loc(ctx), name, args, returnType, body)); + } + + virtual std::any visitFnDeclArgs(plsmParser::FnDeclArgsContext *ctx) override + { + std::vector args; + + for (size_t i = 0; i < ctx->children.size(); i++) + { + std::string name; + if (dynamic_cast(ctx->children[i])) + name = ctx->children[i++]->getText(); + + auto type = visitU(ctx->children[i++]); + + args.push_back(new ast::FnArg(loc(ctx), name, type)); + } + + return std::any(args); + } + + virtual std::any visitLet(plsmParser::LetContext *ctx) override + { + auto name = ctx->identifier()->getText(); + + std::unique_ptr type(nullptr); + if (ctx->type()) + type = visitU(ctx->type()); + + auto expr = visitU(ctx->expr()); + + return std::any(new ast::ValDecl(loc(ctx), name, type, expr)); + } + + virtual std::any visitExprStmt(plsmParser::ExprStmtContext *ctx) override + { + auto expr = visitU(ctx->expr()); + return std::any(new ast::ExprStmt(loc(ctx), expr)); + } + + virtual std::any visitType1(plsmParser::Type1Context *ctx) override + { + if (ctx->type0()) + return visit(ctx->type0()); + + if (ctx->children[0]->getText() == "(") + { + if (ctx->type()) + return visit(ctx->type()); + + if (ctx->tupleTypeList()) + { + auto types = visitVU(ctx->tupleTypeList()); + return std::any((ast::Type *)new ast::TupleType(loc(ctx), types)); + } + } + + if (ctx->children[0]->getText() == "[") + { + std::vector> args; + if (ctx->typeList()) + args = visitVU(ctx->typeList()); + + auto returnType = visitU(ctx->type()); + + return std::any((ast::Type *)new ast::ClosureType(loc(ctx), args, returnType)); + } + + throw std::logic_error("type2 not implemented"); + } + + virtual std::any visitType0(plsmParser::Type0Context *ctx) override + { + auto name = ctx->identifier()->getText(); + + if (ctx->typeList()) + { + auto types = visitVU(ctx->typeList()); + return std::any((ast::Type *)new ast::GenericType(loc(ctx), name, types)); + } + + return std::any((ast::Type *)new ast::NamedType(loc(ctx), name)); + } + + virtual std::any visitTupleTypeList(plsmParser::TupleTypeListContext *ctx) override + { + std::vector types; + for (auto &type : ctx->type()) + types.push_back(visitT(type)); + + return std::any(types); + } + + virtual std::any visitTypeList(plsmParser::TypeListContext *ctx) override + { + std::vector types; + for (auto &type : ctx->type()) + types.push_back(visitT(type)); + + return std::any(types); + } + + virtual std::any visitExpr3(plsmParser::Expr3Context *ctx) override + { + if (ctx->expr2()) + return visit(ctx->expr2()); + + // closure + if (ctx->children[0]->getText() == "[") + { + std::vector args; + if (ctx->identifierList()) + args = visitT>(ctx->identifierList()); + + auto body = visitU(ctx->expr()); + + return std::any((ast::Expr *)new ast::Closure(loc(ctx), args, body)); + } + + // block + if (ctx->children[0]->getText() == "{") + { + std::vector> stmts; + for (auto &stmt : ctx->blockStmt()) + stmts.push_back(visitU(stmt)); + + auto result = visitU(ctx->expr()); + + return std::any((ast::Expr *)new ast::BlockExpr(loc(ctx), stmts, result)); + } + + throw std::logic_error("expr3 not implemented"); + } + + virtual std::any visitExpr2(plsmParser::Expr2Context *ctx) override + { + if (ctx->expr2()) + { + auto left = visitU(ctx->expr2()); + auto op = ctx->operator_()->getText(); + auto right = visitU(ctx->expr1()); + return std::any((ast::Expr *)new ast::BinExpr(loc(ctx), left, op, right)); + } + + return visit(ctx->expr1()); + } + + virtual std::any visitExpr1(plsmParser::Expr1Context *ctx) override + { + if (ctx->operator_()) + { + auto op = ctx->operator_()->getText(); + auto expr = visitU(ctx->expr0()); + return std::any((ast::Expr *)new ast::UnaryExpr(loc(ctx), op, expr)); + } + + return visit(ctx->expr0()); + } + + virtual std::any visitExpr0(plsmParser::Expr0Context *ctx) override + { + if (ctx->literal()) + return visit(ctx->literal()); + + if (ctx->expr()) + { + auto expr = visitU(ctx->expr()); + return std::any((ast::Expr *)new ast::PrefExpr(loc(ctx), expr)); + } + + if (ctx->expr0()) + { + auto expr = visitU(ctx->expr0()); + + // property accessor + if (ctx->identifier()) + { + auto name = ctx->identifier()->getText(); + return std::any((ast::Expr *)new ast::PropExpr(loc(ctx), expr, name)); + } + + // function/closure call + std::vector> args; + if (ctx->exprList()) + args = visitVU(ctx->exprList()); + + return std::any((ast::Expr *)new ast::CallExpr(loc(ctx), expr, args)); + } + + // tuple + if (ctx->tupleExprList()) + { + auto values = visitVU(ctx->tupleExprList()); + return std::any((ast::Expr *)new ast::Tuple(loc(ctx), values)); + } + + // identifier + if (ctx->identifier()) + { + auto name = ctx->identifier()->getText(); + return std::any((ast::Expr *)new ast::Identifier(loc(ctx), name)); + } + + throw std::logic_error("expr0 not implemented"); + } + + virtual std::any visitBlockStmt(plsmParser::BlockStmtContext *ctx) override + { + ast::Stmt *stmt; + + if (ctx->let()) + stmt = (ast::Stmt *)visitT(ctx->let()); + if (ctx->exprStmt()) + stmt = (ast::Stmt *)visitT(ctx->exprStmt()); + if (ctx->fnDef()) + stmt = (ast::Stmt *)visitT(ctx->fnDef()); + + return std::any(stmt); + } + + virtual std::any visitTupleExprList(plsmParser::TupleExprListContext *ctx) override + { + std::vector exprs; + for (auto &expr : ctx->expr()) + exprs.push_back(visitT(expr)); + + return std::any(exprs); + } + + virtual std::any visitExprList(plsmParser::ExprListContext *ctx) override + { + std::vector exprs; + for (auto &expr : ctx->expr()) + exprs.push_back(visitT(expr)); + + return std::any(exprs); + } + + virtual std::any visitIdentifierList(plsmParser::IdentifierListContext *ctx) override + { + std::vector identifiers; + for (auto &identifier : ctx->identifier()) + identifiers.push_back(visitT(identifier)); + + return std::any(identifiers); + } + + virtual std::any visitLiteral(plsmParser::LiteralContext *ctx) override + { + if (ctx->NULL_) + return std::any((ast::Expr *)new ast::NullValue(loc(ctx))); + + if (ctx->INT_LIT()) + { + auto text = ctx->INT_LIT()->getText(); + + int64_t value; + + if (!text.rfind("0x", 0)) + value = std::strtol(text.substr(2).data(), NULL, 16); + + if (!text.rfind("0o", 0)) + value = std::strtol(text.substr(2).data(), NULL, 8); + + if (!text.rfind("0b", 0)) + value = std::strtol(text.substr(2).data(), NULL, 2); + + return std::any((ast::Expr *)new ast::IntValue(loc(ctx), value)); + } + + if (ctx->FLOAT_LIT()) + { + auto text = ctx->FLOAT_LIT()->getText(); + if (text.at(text.size() - 1) == '.') + text += "0"; + + double value = std::strtod(text.data(), NULL); + return std::any((ast::Expr *)new ast::FloatValue(loc(ctx), value)); + } + + throw std::logic_error("literal not implemented"); + } + }; + + std::unique_ptr parse(const std::string &file, const std::string &input) + { + auto istream = antlr4::ANTLRInputStream(input); + auto lexer = plsmLexer(&istream); + auto tokens = antlr4::CommonTokenStream(&lexer); + auto parser = plsmParser(&tokens); + + std::string error; + ErrorListener listener(file, &error); + parser.removeErrorListeners(); + parser.addErrorListener(&listener); + + auto tree = parser.module(); + + if (error.size()) + throw std::runtime_error(error); + + auto module = std::any_cast(Visitor(file).visitModule(tree)); + return std::unique_ptr(module); + } } std::unique_ptr -adscript::parse(const std::string &input) +adscript::parse(const std::string &file, const std::string &input) { throw std::logic_error("adscript::parse not implemented"); } diff --git a/compiler/src/main.cpp b/compiler/src/main.cpp index cc5d931..a25bf61 100644 --- a/compiler/src/main.cpp +++ b/compiler/src/main.cpp @@ -1,13 +1,17 @@ #include #include +#include #include -static std::stringstream readFile(const std::string &path) +#include "Parser.h" + +static std::string readFile(const std::string &path) { - std::ifstream t(path); - std::stringstream buffer; - buffer << t.rdbuf(); - return buffer; + std::ifstream f(path); + auto data = (std::stringstream() << f.rdbuf()).str(); + f.close(); + + return data; } int main(int argc, char *argv[]) @@ -19,9 +23,23 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + auto input = readFile(argv[1]); + + std::cout << input << std::endl; + + try + { + auto module = plsm::parse(argv[1], input); + } + catch (std::runtime_error &err) + { + std::cerr << err.what() << std::endl; + exit(EXIT_FAILURE); + } + // auto module = Parser().parse(argv[1], readFile(argv[1])); - // auto fn = (ast::FnDecl *)module->stmts.at(0); + // auto fn = (ast::FnDef *)module->stmts.at(0); // std::cout << fn->name << std::endl; // delete module; diff --git a/compiler/thirdparty/llvm-project b/compiler/thirdparty/llvm-project new file mode 160000 index 0000000..525fe44 --- /dev/null +++ b/compiler/thirdparty/llvm-project @@ -0,0 +1 @@ +Subproject commit 525fe4492bbecf357d3580d879f2092bf99c12a2 diff --git a/examples/42.plsm b/examples/42.plsm index 0df96c2..00910d5 100644 --- a/examples/42.plsm +++ b/examples/42.plsm @@ -1,6 +1,8 @@ -import test.test; +module test; -fn main[] Int = 42; +import lib/test; + +fn main[test (Int, Int)] Int = 42; fn test[b Int] Int = { fn helper[] Int = b;