diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 4c35dd73..772f4168 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -51,6 +51,8 @@ add_library(libpl ${LIBRARY_TYPE} source/pl/core/ast/ast_node_variable_decl.cpp source/pl/core/ast/ast_node_while_statement.cpp + source/pl/core/ast/visitors/ast_validator.cpp + source/pl/core/token.cpp source/pl/core/evaluator.cpp source/pl/core/lexer.cpp diff --git a/lib/include/pl/core/ast/ast_node.hpp b/lib/include/pl/core/ast/ast_node.hpp index e7e0703d..316aace4 100644 --- a/lib/include/pl/core/ast/ast_node.hpp +++ b/lib/include/pl/core/ast/ast_node.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -36,6 +37,8 @@ namespace pl::core::ast { void setShouldDocument(bool shouldDocument); [[nodiscard]] bool shouldDocument() const; + virtual void accept(vis::ASTVisitor& v) = 0; + private: Location m_location = Location::Empty(); diff --git a/lib/include/pl/core/ast/ast_node_array_variable_decl.hpp b/lib/include/pl/core/ast/ast_node_array_variable_decl.hpp index 2103155f..229ca6f9 100644 --- a/lib/include/pl/core/ast/ast_node_array_variable_decl.hpp +++ b/lib/include/pl/core/ast/ast_node_array_variable_decl.hpp @@ -36,11 +36,18 @@ namespace pl::core::ast { [[nodiscard]] const std::unique_ptr &getPlacementOffset() const { return this->m_placementOffset; } + [[nodiscard]] const std::unique_ptr &getPlacementSection() const { + return this->m_placementSection; + } [[nodiscard]] bool isConstant() const { return this->m_constant; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::string m_name; std::shared_ptr m_type; diff --git a/lib/include/pl/core/ast/ast_node_attribute.hpp b/lib/include/pl/core/ast/ast_node_attribute.hpp index e7b24af6..51e8ac22 100644 --- a/lib/include/pl/core/ast/ast_node_attribute.hpp +++ b/lib/include/pl/core/ast/ast_node_attribute.hpp @@ -30,6 +30,10 @@ namespace pl::core::ast { return m_aliasNamespaceString; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::string m_attribute; std::vector> m_value; diff --git a/lib/include/pl/core/ast/ast_node_bitfield.hpp b/lib/include/pl/core/ast/ast_node_bitfield.hpp index c148eb49..e2fa97e7 100644 --- a/lib/include/pl/core/ast/ast_node_bitfield.hpp +++ b/lib/include/pl/core/ast/ast_node_bitfield.hpp @@ -28,6 +28,9 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::vector> m_entries; }; diff --git a/lib/include/pl/core/ast/ast_node_bitfield_array_variable_decl.hpp b/lib/include/pl/core/ast/ast_node_bitfield_array_variable_decl.hpp index 1a339fa6..c48fb6ce 100644 --- a/lib/include/pl/core/ast/ast_node_bitfield_array_variable_decl.hpp +++ b/lib/include/pl/core/ast/ast_node_bitfield_array_variable_decl.hpp @@ -36,6 +36,10 @@ namespace pl::core::ast { return this->m_size; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::string m_name; std::shared_ptr m_type; diff --git a/lib/include/pl/core/ast/ast_node_bitfield_field.hpp b/lib/include/pl/core/ast/ast_node_bitfield_field.hpp index 2983edfb..260a99e3 100644 --- a/lib/include/pl/core/ast/ast_node_bitfield_field.hpp +++ b/lib/include/pl/core/ast/ast_node_bitfield_field.hpp @@ -28,6 +28,9 @@ namespace pl::core::ast { [[nodiscard]] virtual std::shared_ptr createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const; void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::string m_name; std::unique_ptr m_size; @@ -38,6 +41,10 @@ namespace pl::core::ast { using ASTNodeBitfieldField::ASTNodeBitfieldField; [[nodiscard]] std::shared_ptr createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const override; + + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } }; class ASTNodeBitfieldFieldSizedType : public ASTNodeBitfieldField { @@ -49,8 +56,15 @@ namespace pl::core::ast { return std::unique_ptr(new ASTNodeBitfieldFieldSizedType(*this)); } + [[nodiscard]] const std::unique_ptr &getType() { + return m_type; + } + [[nodiscard]] std::shared_ptr createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::unique_ptr m_type; }; diff --git a/lib/include/pl/core/ast/ast_node_builtin_type.hpp b/lib/include/pl/core/ast/ast_node_builtin_type.hpp index cb6109f2..40eefbcf 100644 --- a/lib/include/pl/core/ast/ast_node_builtin_type.hpp +++ b/lib/include/pl/core/ast/ast_node_builtin_type.hpp @@ -22,6 +22,9 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: Token::ValueType m_type; api::FunctionParameterCount m_parameterCount; diff --git a/lib/include/pl/core/ast/ast_node_cast.hpp b/lib/include/pl/core/ast/ast_node_cast.hpp index 6f42759d..251dd331 100644 --- a/lib/include/pl/core/ast/ast_node_cast.hpp +++ b/lib/include/pl/core/ast/ast_node_cast.hpp @@ -16,6 +16,16 @@ namespace pl::core::ast { [[nodiscard]] std::unique_ptr evaluate(Evaluator *evaluator) const override; + [[nodiscard]] const std::unique_ptr &getValue() const { + return m_value; + } + [[nodiscard]] const std::unique_ptr &getType() const { + return m_type; + } + + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::unique_ptr castValue(const Token::Literal &literal, Token::ValueType type, const std::shared_ptr &typePattern, Evaluator *evaluator) const; diff --git a/lib/include/pl/core/ast/ast_node_compound_statement.hpp b/lib/include/pl/core/ast/ast_node_compound_statement.hpp index 80d17714..a6f40299 100644 --- a/lib/include/pl/core/ast/ast_node_compound_statement.hpp +++ b/lib/include/pl/core/ast/ast_node_compound_statement.hpp @@ -25,6 +25,9 @@ namespace pl::core::ast { FunctionResult execute(Evaluator *evaluator) const override; void addAttribute(std::unique_ptr &&attribute) override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } public: std::vector> m_statements; bool m_newScope = false; diff --git a/lib/include/pl/core/ast/ast_node_conditional_statement.hpp b/lib/include/pl/core/ast/ast_node_conditional_statement.hpp index bcb9d672..476af4a3 100644 --- a/lib/include/pl/core/ast/ast_node_conditional_statement.hpp +++ b/lib/include/pl/core/ast/ast_node_conditional_statement.hpp @@ -27,6 +27,9 @@ namespace pl::core::ast { return this->m_falseBody; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: [[nodiscard]] bool evaluateCondition(const std::unique_ptr &condition, Evaluator *evaluator) const; diff --git a/lib/include/pl/core/ast/ast_node_control_flow_statement.hpp b/lib/include/pl/core/ast/ast_node_control_flow_statement.hpp index 06f6b555..754a49d2 100644 --- a/lib/include/pl/core/ast/ast_node_control_flow_statement.hpp +++ b/lib/include/pl/core/ast/ast_node_control_flow_statement.hpp @@ -16,6 +16,17 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; FunctionResult execute(Evaluator *evaluator) const override; + [[nodiscard]] ControlFlowStatement getType() const { + return this->m_type; + } + + [[nodiscard]] const std::unique_ptr &getRValue() { + return m_rvalue; + } + + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: ControlFlowStatement m_type; std::unique_ptr m_rvalue; diff --git a/lib/include/pl/core/ast/ast_node_enum.hpp b/lib/include/pl/core/ast/ast_node_enum.hpp index 4db14e84..b356e912 100644 --- a/lib/include/pl/core/ast/ast_node_enum.hpp +++ b/lib/include/pl/core/ast/ast_node_enum.hpp @@ -33,6 +33,9 @@ namespace pl::core::ast { [[nodiscard]] const std::unique_ptr &getUnderlyingType() { return this->m_underlyingType; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::map, std::unique_ptr>> m_entries; std::unique_ptr m_underlyingType; diff --git a/lib/include/pl/core/ast/ast_node_function_call.hpp b/lib/include/pl/core/ast/ast_node_function_call.hpp index 33d328ff..98ddc847 100644 --- a/lib/include/pl/core/ast/ast_node_function_call.hpp +++ b/lib/include/pl/core/ast/ast_node_function_call.hpp @@ -26,6 +26,9 @@ namespace pl::core::ast { [[nodiscard]] std::unique_ptr evaluate(Evaluator *evaluator) const override; FunctionResult execute(Evaluator *evaluator) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::string m_functionName; std::vector> m_params; diff --git a/lib/include/pl/core/ast/ast_node_function_definition.hpp b/lib/include/pl/core/ast/ast_node_function_definition.hpp index e722030c..2ba326c3 100644 --- a/lib/include/pl/core/ast/ast_node_function_definition.hpp +++ b/lib/include/pl/core/ast/ast_node_function_definition.hpp @@ -35,6 +35,9 @@ namespace pl::core::ast { return this->m_defaultParameters; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::string m_name; diff --git a/lib/include/pl/core/ast/ast_node_imported_type.hpp b/lib/include/pl/core/ast/ast_node_imported_type.hpp index 18a83785..2ffcee0d 100644 --- a/lib/include/pl/core/ast/ast_node_imported_type.hpp +++ b/lib/include/pl/core/ast/ast_node_imported_type.hpp @@ -16,6 +16,14 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; std::unique_ptr evaluate(Evaluator *evaluator) const override; + [[nodiscard]] const std::string &getImportedTypename() const { + return m_importedTypeName; + } + + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::string m_importedTypeName; }; diff --git a/lib/include/pl/core/ast/ast_node_literal.hpp b/lib/include/pl/core/ast/ast_node_literal.hpp index 38c6f189..62223918 100644 --- a/lib/include/pl/core/ast/ast_node_literal.hpp +++ b/lib/include/pl/core/ast/ast_node_literal.hpp @@ -16,6 +16,9 @@ namespace pl::core::ast { [[nodiscard]] const auto &getValue() const { return this->m_literal; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: Token::Literal m_literal; diff --git a/lib/include/pl/core/ast/ast_node_lvalue_assignment.hpp b/lib/include/pl/core/ast/ast_node_lvalue_assignment.hpp index 0f58ba9d..34f5f048 100644 --- a/lib/include/pl/core/ast/ast_node_lvalue_assignment.hpp +++ b/lib/include/pl/core/ast/ast_node_lvalue_assignment.hpp @@ -34,6 +34,9 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; FunctionResult execute(Evaluator *evaluator) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::string m_lvalueName; std::unique_ptr m_rvalue; diff --git a/lib/include/pl/core/ast/ast_node_match_statement.hpp b/lib/include/pl/core/ast/ast_node_match_statement.hpp index c6055bdb..a9a1428f 100644 --- a/lib/include/pl/core/ast/ast_node_match_statement.hpp +++ b/lib/include/pl/core/ast/ast_node_match_statement.hpp @@ -45,6 +45,17 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; FunctionResult execute(Evaluator *evaluator) const override; + [[nodiscard]] const std::optional &getDefaultCase() const { + return this->m_defaultCase; + } + [[nodiscard]] const std::vector &getNonDefaultCases() const { + return this->m_cases; + } + + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: [[nodiscard]] bool evaluateCondition(const std::unique_ptr &condition, Evaluator *evaluator) const; [[nodiscard]] const std::vector>* getCaseBody(Evaluator *evaluator) const; diff --git a/lib/include/pl/core/ast/ast_node_mathematical_expression.hpp b/lib/include/pl/core/ast/ast_node_mathematical_expression.hpp index a71034e3..26f64197 100644 --- a/lib/include/pl/core/ast/ast_node_mathematical_expression.hpp +++ b/lib/include/pl/core/ast/ast_node_mathematical_expression.hpp @@ -95,6 +95,10 @@ namespace pl::core::ast { [[nodiscard]] const std::unique_ptr &getRightOperand() const { return this->m_right; } [[nodiscard]] Token::Operator getOperator() const { return this->m_operator; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::unique_ptr m_left, m_right; Token::Operator m_operator; diff --git a/lib/include/pl/core/ast/ast_node_multi_variable_decl.hpp b/lib/include/pl/core/ast/ast_node_multi_variable_decl.hpp index aaa69941..c7dd5c08 100644 --- a/lib/include/pl/core/ast/ast_node_multi_variable_decl.hpp +++ b/lib/include/pl/core/ast/ast_node_multi_variable_decl.hpp @@ -20,6 +20,10 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; FunctionResult execute(Evaluator *evaluator) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::vector> m_variables; }; diff --git a/lib/include/pl/core/ast/ast_node_parameter_pack.hpp b/lib/include/pl/core/ast/ast_node_parameter_pack.hpp index efbe978d..28fd9f25 100644 --- a/lib/include/pl/core/ast/ast_node_parameter_pack.hpp +++ b/lib/include/pl/core/ast/ast_node_parameter_pack.hpp @@ -16,6 +16,10 @@ namespace pl::core::ast { return this->m_values; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::vector m_values; }; diff --git a/lib/include/pl/core/ast/ast_node_pointer_variable_decl.hpp b/lib/include/pl/core/ast/ast_node_pointer_variable_decl.hpp index 48668b3b..a404455c 100644 --- a/lib/include/pl/core/ast/ast_node_pointer_variable_decl.hpp +++ b/lib/include/pl/core/ast/ast_node_pointer_variable_decl.hpp @@ -22,9 +22,14 @@ namespace pl::core::ast { [[nodiscard]] constexpr const std::shared_ptr &getType() const { return this->m_type; } [[nodiscard]] constexpr const std::shared_ptr &getSizeType() const { return this->m_sizeType; } [[nodiscard]] constexpr const std::unique_ptr &getPlacementOffset() const { return this->m_placementOffset; } + [[nodiscard]] constexpr const std::unique_ptr &getPlacementSection() const { return this->m_placementSection; } void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::string m_name; std::shared_ptr m_type; diff --git a/lib/include/pl/core/ast/ast_node_rvalue.hpp b/lib/include/pl/core/ast/ast_node_rvalue.hpp index bfa5d5f2..9e8f19a2 100644 --- a/lib/include/pl/core/ast/ast_node_rvalue.hpp +++ b/lib/include/pl/core/ast/ast_node_rvalue.hpp @@ -23,6 +23,10 @@ namespace pl::core::ast { [[nodiscard]] std::unique_ptr evaluate(Evaluator *evaluator) const override; void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: Path m_path; }; diff --git a/lib/include/pl/core/ast/ast_node_rvalue_assignment.hpp b/lib/include/pl/core/ast/ast_node_rvalue_assignment.hpp index 323d48c6..c37d93e8 100644 --- a/lib/include/pl/core/ast/ast_node_rvalue_assignment.hpp +++ b/lib/include/pl/core/ast/ast_node_rvalue_assignment.hpp @@ -24,6 +24,10 @@ namespace pl::core::ast { void createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const override; FunctionResult execute(Evaluator *evaluator) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::unique_ptr m_lvalue, m_rvalue; }; diff --git a/lib/include/pl/core/ast/ast_node_scope_resolution.hpp b/lib/include/pl/core/ast/ast_node_scope_resolution.hpp index 4a151a56..4ed9a3c4 100644 --- a/lib/include/pl/core/ast/ast_node_scope_resolution.hpp +++ b/lib/include/pl/core/ast/ast_node_scope_resolution.hpp @@ -16,6 +16,17 @@ namespace pl::core::ast { [[nodiscard]] std::unique_ptr evaluate(Evaluator *evaluator) const override; + [[nodiscard]] const std::shared_ptr &getType() { + return m_type; + } + [[nodiscard]] const std::string &getName() { + return m_name; + } + + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::shared_ptr m_type; std::string m_name; diff --git a/lib/include/pl/core/ast/ast_node_struct.hpp b/lib/include/pl/core/ast/ast_node_struct.hpp index 6d2f3472..15285ffd 100644 --- a/lib/include/pl/core/ast/ast_node_struct.hpp +++ b/lib/include/pl/core/ast/ast_node_struct.hpp @@ -23,6 +23,10 @@ namespace pl::core::ast { [[nodiscard]] const std::vector> &getInheritance() const { return this->m_inheritance; } void addInheritance(std::shared_ptr &&node) { this->m_inheritance.push_back(std::move(node)); } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::vector> m_members; std::vector> m_inheritance; diff --git a/lib/include/pl/core/ast/ast_node_template_parameter.hpp b/lib/include/pl/core/ast/ast_node_template_parameter.hpp index 33e5c997..5437e33b 100644 --- a/lib/include/pl/core/ast/ast_node_template_parameter.hpp +++ b/lib/include/pl/core/ast/ast_node_template_parameter.hpp @@ -23,6 +23,10 @@ namespace pl::core::ast { return this->m_isType; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: Token::Identifier m_name; bool m_isType; diff --git a/lib/include/pl/core/ast/ast_node_ternary_expression.hpp b/lib/include/pl/core/ast/ast_node_ternary_expression.hpp index 06636ce7..dda63fdc 100644 --- a/lib/include/pl/core/ast/ast_node_ternary_expression.hpp +++ b/lib/include/pl/core/ast/ast_node_ternary_expression.hpp @@ -20,6 +20,10 @@ namespace pl::core::ast { [[nodiscard]] const std::unique_ptr &getThirdOperand() const { return this->m_third; } [[nodiscard]] Token::Operator getOperator() const { return this->m_operator; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::unique_ptr m_first, m_second, m_third; Token::Operator m_operator; diff --git a/lib/include/pl/core/ast/ast_node_try_catch_statement.hpp b/lib/include/pl/core/ast/ast_node_try_catch_statement.hpp index fe566353..077fdc8c 100644 --- a/lib/include/pl/core/ast/ast_node_try_catch_statement.hpp +++ b/lib/include/pl/core/ast/ast_node_try_catch_statement.hpp @@ -23,6 +23,10 @@ namespace pl::core::ast { return this->m_catchBody; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::vector> m_tryBody, m_catchBody; diff --git a/lib/include/pl/core/ast/ast_node_type_appilication.hpp b/lib/include/pl/core/ast/ast_node_type_appilication.hpp index be68c677..702ce894 100644 --- a/lib/include/pl/core/ast/ast_node_type_appilication.hpp +++ b/lib/include/pl/core/ast/ast_node_type_appilication.hpp @@ -18,6 +18,9 @@ namespace pl::core::ast { void setTemplateArguments(std::vector> &&arguments) { this->m_templateArguments = std::move(arguments); } + const std::vector>& getTemplateArguments() { + return this->m_templateArguments; + } std::vector> evaluateTemplateArguments(Evaluator *evaluator) const; @@ -54,6 +57,9 @@ namespace pl::core::ast { return this->m_templateParameterIndex; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } private: std::shared_ptr m_type; std::vector> m_templateArguments; diff --git a/lib/include/pl/core/ast/ast_node_type_decl.hpp b/lib/include/pl/core/ast/ast_node_type_decl.hpp index 162e7b5d..e1fb34cc 100644 --- a/lib/include/pl/core/ast/ast_node_type_decl.hpp +++ b/lib/include/pl/core/ast/ast_node_type_decl.hpp @@ -58,6 +58,13 @@ namespace pl::core::ast { return this->m_templateParameters; } + [[nodiscard]] const std::vector> &getTemplateArguments() const { + return m_templateArguments; + } + [[nodiscard]] const std::unique_ptr &getCurrTemplateParameterType() const { + return m_currTemplateParameterType; + } + void setTemplateParameters(std::vector> &&types) { this->m_templateParameters = std::move(types); } @@ -66,6 +73,10 @@ namespace pl::core::ast { const ASTNode* getTypeDefinition(Evaluator *evaluator) const; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: bool m_forwardDeclared = false; bool m_completed = false; diff --git a/lib/include/pl/core/ast/ast_node_type_operator.hpp b/lib/include/pl/core/ast/ast_node_type_operator.hpp index fd5156e6..e6d7bc35 100644 --- a/lib/include/pl/core/ast/ast_node_type_operator.hpp +++ b/lib/include/pl/core/ast/ast_node_type_operator.hpp @@ -24,6 +24,10 @@ namespace pl::core::ast { [[nodiscard]] std::unique_ptr evaluate(Evaluator *evaluator) const override; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: Token::Operator m_op; std::unique_ptr m_expression; diff --git a/lib/include/pl/core/ast/ast_node_union.hpp b/lib/include/pl/core/ast/ast_node_union.hpp index 1d6f7a29..6bfef239 100644 --- a/lib/include/pl/core/ast/ast_node_union.hpp +++ b/lib/include/pl/core/ast/ast_node_union.hpp @@ -20,6 +20,10 @@ namespace pl::core::ast { [[nodiscard]] const std::vector> &getMembers() const { return this->m_members; } void addMember(std::shared_ptr &&node) { this->m_members.push_back(std::move(node)); } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::vector> m_members; }; diff --git a/lib/include/pl/core/ast/ast_node_variable_decl.hpp b/lib/include/pl/core/ast/ast_node_variable_decl.hpp index a0e0f8d0..ce37f7aa 100644 --- a/lib/include/pl/core/ast/ast_node_variable_decl.hpp +++ b/lib/include/pl/core/ast/ast_node_variable_decl.hpp @@ -22,6 +22,8 @@ namespace pl::core::ast { [[nodiscard]] const std::string &getName() const { return this->m_name; } [[nodiscard]] constexpr const std::shared_ptr &getType() const { return this->m_type; } [[nodiscard]] constexpr const std::unique_ptr &getPlacementOffset() const { return this->m_placementOffset; } + [[nodiscard]] constexpr const std::unique_ptr &getPlacementSection() const { return this->m_placementSection; } + [[nodiscard]] constexpr const std::unique_ptr &getDefaultValue() const { return this->m_defaultValue; } [[nodiscard]] constexpr bool isInVariable() const { return this->m_inVariable; } [[nodiscard]] constexpr bool isOutVariable() const { return this->m_outVariable; } @@ -34,6 +36,10 @@ namespace pl::core::ast { return this->m_constant; } + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: u128 evaluatePlacementOffset(Evaluator *evaluator) const; u64 evaluatePlacementSection(Evaluator *evaluator) const; diff --git a/lib/include/pl/core/ast/ast_node_while_statement.hpp b/lib/include/pl/core/ast/ast_node_while_statement.hpp index 30408c68..9dbc759c 100644 --- a/lib/include/pl/core/ast/ast_node_while_statement.hpp +++ b/lib/include/pl/core/ast/ast_node_while_statement.hpp @@ -22,11 +22,18 @@ namespace pl::core::ast { [[nodiscard]] const std::vector> &getBody() const { return this->m_body; } + [[nodiscard]] const std::unique_ptr &getPostExpression() const { + return this->m_postExpression; + } FunctionResult execute(Evaluator *evaluator) const override; [[nodiscard]] bool evaluateCondition(Evaluator *evaluator) const; + void accept(vis::ASTVisitor &v) override { + v.visit(*this); + } + private: std::unique_ptr m_condition; std::vector> m_body; diff --git a/lib/include/pl/core/ast/visitors/ast_validator.hpp b/lib/include/pl/core/ast/visitors/ast_validator.hpp new file mode 100644 index 00000000..fd7142b5 --- /dev/null +++ b/lib/include/pl/core/ast/visitors/ast_validator.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace pl::core { + + namespace ast { class ASTNode; } + + class ASTValidator : public err::ErrorCollector, ast::vis::ASTVisitor { + using Result = hlp::CompileResult; + public: + ASTValidator() = default; + + Result validate(const std::vector> &ast); + + protected: + virtual void reset() = 0; + + // Helpers + template + void visitTypeErased(const T& node) { + auto nodePtr = node.get(); + if (m_validatedNodes.contains(nodePtr)) { + // Seen this one, let's not repeat ourselves... + return; + } + if (nodePtr == nullptr) { + errorDesc("Null-Pointer found in AST.", "This is a parser bug. Please report it on GitHub."); + return; + } + m_lastNode = nodePtr; + nodePtr->accept(*this); + } + template + void visitTyped(const TypedNode& node) { + auto nodePtr = node.get(); + if (m_validatedNodes.contains(nodePtr)) { + // Seen this one, let's not repeat ourselves... + return; + } + if (nodePtr == nullptr) { + errorDesc("Null-Pointer found in AST.", "This is a parser bug. Please report it on GitHub."); + return; + } + m_lastNode = nodePtr; + visit(*nodePtr); + } + + template + void visitTypeErasedNodes(const std::vector& nodes) { + for (const auto& node_like: nodes) { + visitTypeErased(node_like); + } + } + template + void visitTypedNodes(const std::vector& nodes) { + for (const auto& node_like: nodes) { + visitTyped(node_like); + } + } + + + // No default action + void visit(ast::ASTNode& node) override { wolv::util::unused(node); }; + void visit(ast::ASTNodeArrayVariableDecl& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeAttribute& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeBitfield& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeBitfieldArrayVariableDecl& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeBitfieldField& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeBitfieldFieldSigned& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeBitfieldFieldSizedType& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeBuiltinType& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeCast& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeCompoundStatement& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeConditionalStatement& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeControlFlowStatement& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeEnum& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeFunctionCall& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeFunctionDefinition& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeImportedType& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeLiteral& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeLValueAssignment& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeMatchStatement& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeMathematicalExpression& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeMultiVariableDecl& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeParameterPack& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodePointerVariableDecl& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeRValue& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeRValueAssignment& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeScopeResolution& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeStruct& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeTemplateParameter& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeTernaryExpression& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeTryCatchStatement& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeTypeApplication& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeTypeDecl& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeTypeOperator& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeUnion& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeVariableDecl& node) override { wolv::util::unused(node); } + void visit(ast::ASTNodeWhileStatement& node) override { wolv::util::unused(node); } + + Location location() override; + + ast::ASTNode *m_lastNode = nullptr; + std::set m_validatedNodes; + }; + +} diff --git a/lib/include/pl/core/ast/visitors/ast_visitor.hpp b/lib/include/pl/core/ast/visitors/ast_visitor.hpp new file mode 100644 index 00000000..8bc63891 --- /dev/null +++ b/lib/include/pl/core/ast/visitors/ast_visitor.hpp @@ -0,0 +1,105 @@ +#pragma once + +#include +#include + +namespace pl::core::ast { + // Forward declarations + class ASTNode; + class ASTNodeArrayVariableDecl; + class ASTNodeAttribute; + class ASTNodeBitfield; + class ASTNodeBitfieldArrayVariableDecl; + class ASTNodeBitfieldField; + class ASTNodeBitfieldFieldSigned; + class ASTNodeBitfieldFieldSizedType; + class ASTNodeBuiltinType; + class ASTNodeCast; + class ASTNodeCompoundStatement; + class ASTNodeConditionalStatement; + class ASTNodeControlFlowStatement; + class ASTNodeEnum; + class ASTNodeFunctionCall; + class ASTNodeFunctionDefinition; + class ASTNodeImportedType; + class ASTNodeLiteral; + class ASTNodeLValueAssignment; + class ASTNodeMatchStatement; + class ASTNodeMathematicalExpression; + class ASTNodeMultiVariableDecl; + class ASTNodeParameterPack; + class ASTNodePointerVariableDecl; + class ASTNodeRValue; + class ASTNodeRValueAssignment; + class ASTNodeScopeResolution; + class ASTNodeStruct; + class ASTNodeTemplateParameter; + class ASTNodeTernaryExpression; + class ASTNodeTryCatchStatement; + class ASTNodeTypeApplication; + class ASTNodeTypeDecl; + class ASTNodeTypeOperator; + class ASTNodeUnion; + class ASTNodeVariableDecl; + class ASTNodeWhileStatement; + + + namespace vis { + class ASTVisitor; + + template + concept PointerToDerivedFrom = std::is_pointer_v && + std::derived_from, Base>; + + template + concept Acceptable = requires(T obj) { + static_cast(obj); + { obj.get() } -> PointerToDerivedFrom; + (*obj).accept(std::declval()); + }; + + class ASTVisitor { + public: + virtual ~ASTVisitor() = default; + + // Overrideable + virtual void visit(ASTNode& node) = 0; + virtual void visit(ASTNodeArrayVariableDecl& node) = 0; + virtual void visit(ASTNodeAttribute& node) = 0; + virtual void visit(ASTNodeBitfield& node) = 0; + virtual void visit(ASTNodeBitfieldArrayVariableDecl& node) = 0; + virtual void visit(ASTNodeBitfieldField& node) = 0; + virtual void visit(ASTNodeBitfieldFieldSigned& node) = 0; + virtual void visit(ASTNodeBitfieldFieldSizedType& node) = 0; + virtual void visit(ASTNodeBuiltinType& node) = 0; + virtual void visit(ASTNodeCast& node) = 0; + virtual void visit(ASTNodeCompoundStatement& node) = 0; + virtual void visit(ASTNodeConditionalStatement& node) = 0; + virtual void visit(ASTNodeControlFlowStatement& node) = 0; + virtual void visit(ASTNodeEnum& node) = 0; + virtual void visit(ASTNodeFunctionCall& node) = 0; + virtual void visit(ASTNodeFunctionDefinition& node) = 0; + virtual void visit(ASTNodeImportedType& node) = 0; + virtual void visit(ASTNodeLiteral& node) = 0; + virtual void visit(ASTNodeLValueAssignment& node) = 0; + virtual void visit(ASTNodeMatchStatement& node) = 0; + virtual void visit(ASTNodeMathematicalExpression& node) = 0; + virtual void visit(ASTNodeMultiVariableDecl& node) = 0; + virtual void visit(ASTNodeParameterPack& node) = 0; + virtual void visit(ASTNodePointerVariableDecl& node) = 0; + virtual void visit(ASTNodeRValue& node) = 0; + virtual void visit(ASTNodeRValueAssignment& node) = 0; + virtual void visit(ASTNodeScopeResolution& node) = 0; + virtual void visit(ASTNodeStruct& node) = 0; + virtual void visit(ASTNodeTemplateParameter& node) = 0; + virtual void visit(ASTNodeTernaryExpression& node) = 0; + virtual void visit(ASTNodeTryCatchStatement& node) = 0; + virtual void visit(ASTNodeTypeApplication& node) = 0; + virtual void visit(ASTNodeTypeDecl& node) = 0; + virtual void visit(ASTNodeTypeOperator& node) = 0; + virtual void visit(ASTNodeUnion& node) = 0; + virtual void visit(ASTNodeVariableDecl& node) = 0; + virtual void visit(ASTNodeWhileStatement& node) = 0; + }; + } +} diff --git a/lib/include/pl/core/validator.hpp b/lib/include/pl/core/validator.hpp index 5c9719a5..0cae19c1 100644 --- a/lib/include/pl/core/validator.hpp +++ b/lib/include/pl/core/validator.hpp @@ -12,6 +12,8 @@ #include +#include + namespace pl::core { namespace ast { class ASTNode; } @@ -43,4 +45,23 @@ namespace pl::core { std::list> m_identifiers; }; + class ValidatorPipeline { + public: + using Result = hlp::CompileResult; + + ValidatorPipeline() = default; + + template ... Vs> + ValidatorPipeline(std::unique_ptr... validators) { + (add(validators), ...); + } + + void add(std::unique_ptr validator); + + Result validate(const std::vector> &ast); + + private: + std::vector> m_validators; + }; + } diff --git a/lib/include/pl/pattern_language.hpp b/lib/include/pl/pattern_language.hpp index 8147697a..337c1b17 100644 --- a/lib/include/pl/pattern_language.hpp +++ b/lib/include/pl/pattern_language.hpp @@ -32,6 +32,7 @@ namespace pl { class Lexer; class Parser; class Validator; + class ValidatorPipeline; class Evaluator; namespace ast { class ASTNode; } @@ -61,11 +62,12 @@ namespace pl { PatternLanguage(PatternLanguage &&other) noexcept; struct Internals { - std::unique_ptr preprocessor; - std::unique_ptr lexer; - std::unique_ptr parser; - std::unique_ptr validator; - std::unique_ptr evaluator; + std::unique_ptr preprocessor; + std::unique_ptr lexer; + std::unique_ptr parser; + std::unique_ptr validator; + std::unique_ptr validatorPipeline; + std::unique_ptr evaluator; }; /** diff --git a/lib/source/pl/core/ast/visitors/ast_validator.cpp b/lib/source/pl/core/ast/visitors/ast_validator.cpp new file mode 100644 index 00000000..35b69085 --- /dev/null +++ b/lib/source/pl/core/ast/visitors/ast_validator.cpp @@ -0,0 +1,59 @@ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pl::core { + ASTValidator::Result ASTValidator::validate(const std::vector> &ast) { + this->m_validatedNodes.clear(); + + // Other validator-specific cleanup: + reset(); + + visitTypeErasedNodes(ast); + + if(this->hasErrors()) { + return Result::err(this->collectErrors()); + } + return { }; + } + + Location ASTValidator::location() { + return m_lastNode->getLocation(); + } +} \ No newline at end of file diff --git a/lib/source/pl/core/validator.cpp b/lib/source/pl/core/validator.cpp index 0af78364..d4939373 100644 --- a/lib/source/pl/core/validator.cpp +++ b/lib/source/pl/core/validator.cpp @@ -199,5 +199,33 @@ namespace pl::core { return m_lastNode->getLocation(); } + void ValidatorPipeline::add(std::unique_ptr validator) { + m_validators.push_back(std::move(validator)); + } + + ValidatorPipeline::Result ValidatorPipeline::validate(const std::vector> &ast) { + using ValidatorErrors = std::vector; + + std::vector pipeline_errors; + size_t errorsCount = 0; + + for (auto& validator: m_validators) { + auto [_, errors] = validator->validate(ast); + errorsCount += errors.size(); + pipeline_errors.push_back(std::move(errors)); + } + + if (errorsCount == 0) { + return { }; + } + // We have some errors + + std::vector result; + result.reserve(errorsCount); + for (auto& errors: pipeline_errors) { + std::move(errors.begin(), errors.end(), std::back_inserter(result)); + } + return Result::err(std::move(result)); + } } \ No newline at end of file diff --git a/lib/source/pl/pattern_language.cpp b/lib/source/pl/pattern_language.cpp index 0841e45f..43e7e33e 100644 --- a/lib/source/pl/pattern_language.cpp +++ b/lib/source/pl/pattern_language.cpp @@ -34,11 +34,12 @@ namespace pl { PatternLanguage::PatternLanguage(const bool addLibStd) { this->m_internals = { - .preprocessor = std::make_unique(), - .lexer = std::make_unique(), - .parser = std::make_unique(), - .validator = std::make_unique(), - .evaluator = std::make_unique() + .preprocessor = std::make_unique(), + .lexer = std::make_unique(), + .parser = std::make_unique(), + .validator = std::make_unique(), + .validatorPipeline = std::make_unique(), + .evaluator = std::make_unique() }; this->m_internals.evaluator->setRuntime(this); @@ -167,7 +168,7 @@ namespace pl { this->m_internals.parser->setParserManager(&this->m_parserManager); auto [ast, parserErrors] = this->m_internals.parser->parse(tokens.value()); if (!parserErrors.empty()) { - this->m_compileErrors.insert(m_compileErrors.end(), parserErrors.begin(), parserErrors.end()); + std::ranges::move(parserErrors, std::back_inserter(m_compileErrors)); parserErrors.clear(); } @@ -185,7 +186,13 @@ namespace pl { this->m_compileErrors.insert(m_compileErrors.end(), validatorErrors.begin(), validatorErrors.end()); validatorErrors.clear(); } + // TODO: delete the block above when ready + auto [_, validatorPipelineErrors] = this->m_internals.validatorPipeline->validate(ast.value()); + if (!validatorPipelineErrors.empty()) { + std::ranges::move(validatorPipelineErrors, std::back_inserter(m_compileErrors)); + validatorPipelineErrors.clear(); + } this->m_internals.preprocessor->setStoredErrors(this->m_compileErrors); @@ -672,5 +679,4 @@ namespace pl { const std::set& PatternLanguage::getPatternsWithAttribute(const std::string &attribute) const { return m_internals.evaluator->getPatternsWithAttribute(attribute); } - -} \ No newline at end of file +}