Nicolas Winkler 7 years ago
parent
commit
d2b0f5c470
6 changed files with 136 additions and 52 deletions
  1. 18 16
      src/Ast.cpp
  2. 10 11
      src/Ast.h
  3. 6 0
      src/AstVisitor.cpp
  4. 7 21
      src/Semantic.cpp
  5. 70 1
      src/Semantic.h
  6. 25 3
      src/Util.h

+ 18 - 16
src/Ast.cpp

@@ -10,26 +10,28 @@ AstObject::~AstObject(void)
 }
 
 
-#define ACCEPT_DEFINITION(ClassName) \
-std::unique_ptr<qlow::sem::SemanticObject> ClassName::accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>& c) \
+#define ACCEPT_DEFINITION(ClassName, Visitor) \
+std::unique_ptr<qlow::sem::SemanticObject> ClassName::accept(Visitor& v, const sem::SymbolTable<sem::Class>& c) \
 { \
     v.visit(*this, c); \
 }
 
-ACCEPT_DEFINITION(Class)
-ACCEPT_DEFINITION(FeatureDeclaration)
-ACCEPT_DEFINITION(FieldDeclaration)
-ACCEPT_DEFINITION(MethodDefinition)
-ACCEPT_DEFINITION(VariableDeclaration)
-ACCEPT_DEFINITION(ArgumentDeclaration)
-ACCEPT_DEFINITION(DoEndBlock)
-ACCEPT_DEFINITION(Statement)
-ACCEPT_DEFINITION(Expression)
-ACCEPT_DEFINITION(FeatureCall)
-ACCEPT_DEFINITION(AssignmentStatement)
-ACCEPT_DEFINITION(NewVariableStatement)
-ACCEPT_DEFINITION(UnaryOperation)
-ACCEPT_DEFINITION(BinaryOperation)
+ACCEPT_DEFINITION(Class, StructureVisitor)
+ACCEPT_DEFINITION(FeatureDeclaration, StructureVisitor)
+ACCEPT_DEFINITION(FieldDeclaration, StructureVisitor)
+ACCEPT_DEFINITION(MethodDefinition, StructureVisitor)
+ACCEPT_DEFINITION(VariableDeclaration, StructureVisitor)
+ACCEPT_DEFINITION(ArgumentDeclaration, StructureVisitor)
+
+
+ACCEPT_DEFINITION(DoEndBlock, BodyVisitor)
+ACCEPT_DEFINITION(Statement, BodyVisitor)
+ACCEPT_DEFINITION(Expression, BodyVisitor)
+ACCEPT_DEFINITION(FeatureCall, BodyVisitor)
+ACCEPT_DEFINITION(AssignmentStatement, BodyVisitor)
+ACCEPT_DEFINITION(NewVariableStatement, BodyVisitor)
+ACCEPT_DEFINITION(UnaryOperation, BodyVisitor)
+ACCEPT_DEFINITION(BinaryOperation, BodyVisitor)
 
 
 

+ 10 - 11
src/Ast.h

@@ -29,6 +29,8 @@
 #include <map>
 
 #include "Visitor.h"
+#include "Util.h"
+#include "Util.h"
 
 namespace qlow
 {
@@ -37,9 +39,6 @@ namespace qlow
     class StructureVisitor;
     namespace ast
     {
-        template<typename T>
-        using List = std::vector<std::unique_ptr<T>>;
-
         // base class
         struct AstObject;
 
@@ -106,9 +105,9 @@ struct qlow::ast::AstObject :
 struct qlow::ast::Class : public AstObject
 {
     std::string name;
-    List<FeatureDeclaration> features;
+    OwningList<FeatureDeclaration> features;
     
-    inline Class(const std::string& name, List<FeatureDeclaration>& features, const CodePosition& cp) :
+    inline Class(const std::string& name, OwningList<FeatureDeclaration>& features, const CodePosition& cp) :
         AstObject{ cp },
         name{ name }, features(std::move(features))
     {
@@ -146,7 +145,7 @@ struct qlow::ast::FieldDeclaration : public FeatureDeclaration
 
 struct qlow::ast::MethodDefinition : public FeatureDeclaration
 {
-    List<ArgumentDeclaration> arguments;
+    OwningList<ArgumentDeclaration> arguments;
     std::unique_ptr<DoEndBlock> body;
 
     inline MethodDefinition(const std::string& type, const std::string& name,
@@ -158,7 +157,7 @@ struct qlow::ast::MethodDefinition : public FeatureDeclaration
 
 
     inline MethodDefinition(const std::string& type, const std::string& name,
-            List<ArgumentDeclaration>&& arguments, std::unique_ptr<DoEndBlock> body, const CodePosition& cp) :
+            OwningList<ArgumentDeclaration>&& arguments, std::unique_ptr<DoEndBlock> body, const CodePosition& cp) :
         FeatureDeclaration(type, name, cp),
         arguments(std::move(arguments)),
         body(std::move(body))
@@ -197,9 +196,9 @@ struct qlow::ast::ArgumentDeclaration :
 
 struct qlow::ast::DoEndBlock : public AstObject
 {
-    List<Statement> statements;
+    OwningList<Statement> statements;
     
-    inline DoEndBlock(List<Statement>&& statements, const CodePosition& cp) :
+    inline DoEndBlock(OwningList<Statement>&& statements, const CodePosition& cp) :
         AstObject{ cp },
         statements(std::move(statements))
     {
@@ -233,7 +232,7 @@ struct qlow::ast::FeatureCall : public Expression, public Statement
 {
     std::unique_ptr<Expression> target;
     std::string name;
-    List<Expression> arguments;
+    OwningList<Expression> arguments;
 
     inline FeatureCall(std::unique_ptr<Expression> target, const std::string& name, const CodePosition& cp) :
         AstObject{ cp },
@@ -244,7 +243,7 @@ struct qlow::ast::FeatureCall : public Expression, public Statement
 
 
     inline FeatureCall(std::unique_ptr<Expression> target, const std::string& name,
-            List<Expression>&& arguments, const CodePosition& cp) :
+            OwningList<Expression>&& arguments, const CodePosition& cp) :
         AstObject{ cp },
         Expression{ cp }, Statement{ cp },
         target(std::move(target)), name(name), arguments(std::move(arguments))

+ 6 - 0
src/AstVisitor.cpp

@@ -47,6 +47,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
     auto m = std::make_unique<sem::Method>();
     m->name = ast.name;
     m->returnType = getType(ast.type, classes);
+    m->astNode = &ast;
     if (m->returnType == nullptr) {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
             ast.type,
@@ -79,6 +80,11 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ArgumentDeclar
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& ast, const sem::SymbolTable<sem::Class>& classes)
 {
+    auto body = std::make_unique<sem::DoEndBlock>();
+    for (auto& statement : ast.statements) {
+        body->statements.push_back(unique_dynamic_cast<sem::Statement>(visit(*statement, classes)));
+    }
+    return body;
 }
 
 

+ 7 - 21
src/Semantic.cpp

@@ -10,25 +10,6 @@ namespace qlow
 namespace sem
 {
 
-/// i don't like this, but I lack better ideas at the moment.
-/// TODO: find better solution
-
-/*!
-* \brief tries to cast a unique_ptr and throws if it fails
-*/
-template<typename T, typename U>
-std::unique_ptr<T> unique_dynamic_cast(std::unique_ptr<U>&& p)
-{
-    U* released = p.release();
-    if (T* casted = dynamic_cast<T*>(released); casted)
-        return std::unique_ptr<T> (casted);
-    else {
-        delete released;
-        throw "invalid unique_dynamic_cast";
-    }
-}
-
-
 SymbolTable<qlow::sem::Class>
     createFromAst(std::vector<std::unique_ptr<qlow::ast::Class>>& classes)
 {
@@ -63,10 +44,15 @@ SymbolTable<qlow::sem::Class>
                 // if a feature is neither a method nor a field, something went horribly wrong
                 throw "internal error";
             }
-            
-            
         }
     }
+    
+    for (auto& [name, semClass] : semClasses) {
+        for (auto& [name, method] : semClass->methods) {
+            method->body = unique_dynamic_cast<sem::DoEndBlock>(av.visit(*method->astNode->body, semClasses));
+        }
+    }
+    
     return semClasses;
 }
 

+ 70 - 1
src/Semantic.h

@@ -23,7 +23,19 @@ namespace qlow
         struct Method;
         
         struct Variable;
-        struct Variable;
+        
+        struct DoEndBlock;
+        struct Statement;
+        struct Expression;
+        
+        struct FeatureCallStatement;
+        struct AssignmentStatement;
+
+        struct Operation;
+        struct UnaryOperation;
+        struct BinaryOperation;
+        
+        struct FeatureCallExpression;
 
         SymbolTable<qlow::sem::Class> createFromAst(std::vector<std::unique_ptr<qlow::ast::Class>>& classes);
         
@@ -73,6 +85,8 @@ struct qlow::sem::Method : public SemanticObject
 {
     Class* returnType;
     std::string name;
+    ast::MethodDefinition* astNode;
+    std::unique_ptr<DoEndBlock> body;
     
     virtual std::string toString(void) const override;
 };
@@ -85,6 +99,61 @@ struct qlow::sem::Variable : public SemanticObject
 };
 
 
+struct qlow::sem::DoEndBlock : public SemanticObject
+{
+    OwningList<Variable> variables;
+    OwningList<Statement> statements;
+};
+
+
+struct qlow::sem::Statement : public SemanticObject
+{
+};
+
+
+struct qlow::sem::FeatureCallStatement : public Statement 
+{
+    Method* callee;
+    OwningList<Expression> arguments;
+};
+
+
+struct qlow::sem::AssignmentStatement : public Statement 
+{
+    Variable* target;
+    std::unique_ptr<Expression> value;
+};
+
+
+struct qlow::sem::Expression : public SemanticObject
+{
+};
+
+
+struct qlow::sem::Operation : public Expression
+{
+    ast::Operation::Operator op;
+};
+
+
+struct qlow::sem::BinaryOperation : public Operation
+{
+    std::unique_ptr<Expression> left;
+    std::unique_ptr<Expression> right;
+};
+
+
+struct qlow::sem::UnaryOperation : public Operation
+{
+    std::unique_ptr<Expression> arg;
+};
+
+struct qlow::sem::FeatureCallExpression : public Expression
+{
+    Method* callee;
+    OwningList<Expression> arguments;
+};
+
 
 class qlow::sem::SemanticException
 {

+ 25 - 3
src/Util.h

@@ -8,11 +8,33 @@
 
 namespace qlow
 {
-    namespace util
+    
+    template<typename T>
+    using OwningList = std::vector<std::unique_ptr<T>>;
+    
+    
+    
+    /// i don't like this, but I lack better ideas at the moment.
+    /// TODO: find better solution
+    /*!
+    * \brief tries to cast a unique_ptr and throws if it fails
+    */
+    template<typename T, typename U>
+    std::unique_ptr<T> unique_dynamic_cast(std::unique_ptr<U>&& p)
     {
-        template<typename T>
-        using OwningList = std::vector<std::unique_ptr<T>>;
+        U* released = p.release();
+        if (T* casted = dynamic_cast<T*>(released); casted)
+            return std::unique_ptr<T> (casted);
+        else {
+            delete released;
+            throw "invalid unique_dynamic_cast";
+        }
+    }
 
+
+    
+    namespace util
+    {
         inline std::string toString(const void* a)
         {
             std::ostringstream o;