Forráskód Böngészése

implementing field access

QlowB 6 éve
szülő
commit
6e5d6a484c

+ 16 - 6
src/AstVisitor.cpp

@@ -103,7 +103,10 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Statement& ast
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& ast, sem::Scope& scope)
 {
-    auto body = std::make_unique<sem::DoEndBlock>(scope);
+    sem::LocalScope* lscope = dynamic_cast<sem::LocalScope*>(&scope);
+    if (!lscope)
+        throw "error: non-method scope inside method";
+    auto body = std::make_unique<sem::DoEndBlock>(*lscope);
     for (auto& statement : ast.statements) {
         
         if (ast::LocalVariableStatement* nvs = dynamic_cast<ast::LocalVariableStatement*>(statement.get()); nvs) {
@@ -119,10 +122,10 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
         }
         
         auto v = statement->accept(*this, body->scope);
-        if (dynamic_cast<sem::FeatureCallExpression*>(v.get()) != nullptr) {
+        if (dynamic_cast<sem::MethodCallExpression*>(v.get()) != nullptr) {
             body->statements.push_back(
                 std::make_unique<sem::FeatureCallStatement>(
-                unique_dynamic_cast<sem::FeatureCallExpression>(std::move(v))));
+                unique_dynamic_cast<sem::MethodCallExpression>(std::move(v))));
         }
         else {
             body->statements.push_back(unique_dynamic_cast<sem::Statement>(std::move(v)));
@@ -199,9 +202,10 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
     
     if (target) {
         if (var) {
+            return std::make_unique<sem::FieldAccessExpression>(std::move(target), dynamic_cast<sem::Field*>(var));
         }
         else if (method) {
-            auto fce = std::make_unique<sem::FeatureCallExpression>(
+            auto fce = std::make_unique<sem::MethodCallExpression>(
                 std::move(target), method);
     
             if (ast.arguments.size() != method->arguments.size())
@@ -233,10 +237,16 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
         }
     }
     else if (var) {
-        return std::make_unique<sem::LocalVariableExpression>(var);
+        if (sem::Field* field = dynamic_cast<sem::Field*>(var); field) {
+            auto* thisExpr = scope.getVariable("this");
+            return std::make_unique<sem::FieldAccessExpression>(std::make_unique<sem::LocalVariableExpression>(thisExpr), field);
+        }
+        else {
+            return std::make_unique<sem::LocalVariableExpression>(var);
+        }
     }
     else if (method) {
-        auto fce = std::make_unique<sem::FeatureCallExpression>(nullptr, method);
+        auto fce = std::make_unique<sem::MethodCallExpression>(nullptr, method);
         for (auto& arg : ast.arguments) {
             auto argument = arg->accept(*this, scope);
             if (dynamic_cast<sem::Expression*>(argument.get())) {

+ 14 - 3
src/CodegenVisitor.cpp

@@ -124,7 +124,8 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, ll
     // TODO implement
 }
 
-llvm::Value* ExpressionCodegenVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
+
+llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
     std::vector<Value*> arguments;
@@ -148,6 +149,15 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FeatureCallExpression& call, l
     return callInst;
 }
 
+
+llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
+{
+    using llvm::Value;
+    
+    builder.CreateStructGEP(access.type->getLlvmType(builder.getContext()), llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false)), 0);
+}
+
+
 llvm::Value* ExpressionCodegenVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
 {
     return llvm::ConstantInt::get(builder.getContext(),
@@ -233,6 +243,7 @@ llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
     builder.CreateBr(startloop);
     fg.popBlock();
     fg.pushBlock(merge);
+    return nullptr;
 }
 
 
@@ -249,9 +260,9 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         builder.CreateStore(val, targetVar->var->allocaInst);
     }
     else if (auto* targetVar =
-        dynamic_cast<sem::FeatureCallExpression*>(assignment.target.get()); targetVar) {
+        dynamic_cast<sem::MethodCallExpression*>(assignment.target.get()); targetVar) {
         
-        logger.debug() << "assigning to FeatureCallExpression" << std::endl;
+        logger.debug() << "assigning to MethodCallExpression" << std::endl;
     }
     else {
         

+ 4 - 2
src/CodegenVisitor.h

@@ -40,7 +40,8 @@ class qlow::ExpressionCodegenVisitor :
         sem::BinaryOperation,
         sem::CastExpression,
         sem::NewArrayExpression,
-        sem::FeatureCallExpression,
+        sem::MethodCallExpression,
+        sem::FieldAccessExpression,
         sem::IntConst
     >
 {
@@ -50,7 +51,8 @@ public:
     llvm::Value* visit(sem::BinaryOperation& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::CastExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::NewArrayExpression& node, llvm::IRBuilder<>&) override;
-    llvm::Value* visit(sem::FeatureCallExpression& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::MethodCallExpression& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::FieldAccessExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::IntConst& node, llvm::IRBuilder<>&) override;
 };
 

+ 7 - 6
src/Driver.cpp

@@ -93,11 +93,11 @@ int Driver::run(void)
             errorOccurred = true;
         }
         catch (const char* errMsg) {
-            logger.logError(errMsg);
+            reportError(errMsg);
             errorOccurred = true;
         }
         catch (...) {
-            logger.logError("an unknown error occurred.");
+            reportError("an unknown error occurred.");
             errorOccurred = true;
         }
         
@@ -120,11 +120,11 @@ int Driver::run(void)
         errorOccurred = true;
     }
     catch(const char* err) {
-        logger.logError(err);
+        reportError(err);
         errorOccurred = true;
     }
     catch (...) {
-        logger.logError("an unknown error occurred.");
+        reportError("an unknown error occurred.");
         errorOccurred = true;
     }
     
@@ -165,7 +165,7 @@ int Driver::run(void)
         mod = qlow::gen::generateModule(*semClasses);
     }
     catch (const char* err) {
-        logger.logError(err);
+        reportError(err);
         return 1;
     }
     catch (SemanticError& err) {
@@ -173,7 +173,7 @@ int Driver::run(void)
         return 1;
     }
     catch (...) {
-        logger.logError("unknown error during code generation");
+        reportError("unknown error during code generation");
         return 1;
     }
     
@@ -186,6 +186,7 @@ int Driver::run(void)
     }
     catch (...) {
         logger.logError("unknown error during object file creation");
+        reportError("unknown error during object file creation");
         return 1;
     }
     

+ 14 - 0
src/ErrorReporting.cpp

@@ -16,6 +16,20 @@ namespace qlow
         
         ce.print(logger);
     }
+    
+    
+    void reportError(const std::string& msg)
+    {
+        Logger& logger = Logger::getInstance();
+        
+        logger.logError(msg);
+        
+        logger.info() <<
+            "\n"
+            "This kind of error isn't supposed to happen.\n\n"
+            "Please submit a bug report to nicolas.winkler@gmx.ch\n"
+        ;
+    }
 }
 
 

+ 1 - 0
src/ErrorReporting.h

@@ -14,6 +14,7 @@ namespace qlow
     class SemanticError;
     
     void reportError(const CompileError& ce);
+    void reportError(const std::string& message);
 }
 
 

+ 19 - 0
src/Scope.cpp

@@ -174,6 +174,21 @@ std::shared_ptr<sem::Type> sem::ClassScope::getReturnableType(void)
 }
 
 
+sem::LocalScope::LocalScope(Scope& parentScope, Method* enclosingMethod) :
+    parentScope{ parentScope },
+    returnType{ enclosingMethod->returnType },
+    enclosingMethod{ enclosingMethod }
+{
+}
+
+sem::LocalScope::LocalScope(LocalScope& parentScope) :
+    parentScope{ parentScope },
+    returnType{ parentScope.returnType },
+    enclosingMethod{ parentScope.enclosingMethod }
+{
+}
+
+
 void sem::LocalScope::putVariable(const std::string& name, std::unique_ptr<Variable> v)
 {
     localVariables.insert({name, std::move(v)});
@@ -188,6 +203,10 @@ sem::SymbolTable<sem::Variable>& sem::LocalScope::getLocals(void)
 
 sem::Variable* sem::LocalScope::getVariable(const std::string& name)
 {
+    if (name == "this") {
+        return enclosingMethod->thisExpression.get();
+    }
+    
     auto m = localVariables.find(name);
     if (m != localVariables.end())
         return (*m).second.get();

+ 3 - 17
src/Scope.h

@@ -109,24 +109,10 @@ class qlow::sem::LocalScope : public Scope
     Scope& parentScope;
     SymbolTable<Variable> localVariables;
     std::shared_ptr<Type> returnType;
+    Method* enclosingMethod;
 public:
-    inline LocalScope(Scope& parentScope, Type* returnType) :
-        parentScope{ parentScope },
-        returnType{ returnType }
-    {
-    }
-
-    inline LocalScope(Scope& parentScope) :
-        parentScope{ parentScope }
-    {
-        auto returnable = parentScope.getReturnableType();
-        if (returnable) {
-            returnType = std::move(returnable);
-        }
-        else {
-            returnType = nullptr;
-        }
-    }
+    LocalScope(Scope& parentScope, Method* enclosingMethod);
+    LocalScope(LocalScope& parentScope);
 
     void putVariable(const std::string& name, std::unique_ptr<Variable> v);
     SymbolTable<Variable>& getLocals(void);

+ 11 - 4
src/Semantic.cpp

@@ -88,12 +88,12 @@ std::unique_ptr<GlobalScope>
     for (auto& [name, semClass] : globalScope->classes) {
         for (auto& [name, method] : semClass->methods) {
             if (method->astNode->body) // if not declaration
-                method->body = unique_dynamic_cast<sem::DoEndBlock>(av.visit(*method->astNode->body, method->scope));
+                method->body = unique_dynamic_cast<sem::DoEndBlock>(method->astNode->body->accept(av, method->scope));
         }
     }
     for (auto& [name, method] : globalScope->functions) {
         if (method->astNode->body) // if not declaration
-            method->body = unique_dynamic_cast<sem::DoEndBlock>(av.visit(*method->astNode->body, method->scope));
+            method->body = unique_dynamic_cast<sem::DoEndBlock>(method->astNode->body->accept(av, method->scope));
     }
     
 #ifdef DEBUGGING
@@ -174,7 +174,8 @@ ACCEPT_DEFINITION(BinaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm:
 ACCEPT_DEFINITION(CastExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(NewArrayExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(UnaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(FeatureCallExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(MethodCallExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(FieldAccessExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(IntConst, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 
 ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
@@ -230,12 +231,18 @@ std::string NewArrayExpression::toString(void) const
 }
 
 
-std::string FeatureCallExpression::toString(void) const
+std::string MethodCallExpression::toString(void) const
 {
     return "FeatureCallExpression[" + callee->toString() + "]";
 }
 
 
+std::string FieldAccessExpression::toString(void) const
+{
+    return "FieldAccessExpression[" + accessed->toString() + "]";
+}
+
+
 std::string FeatureCallStatement::toString(void) const
 {
     return "FeatureCallStatement[" + expr->callee->toString() + "]";

+ 46 - 9
src/Semantic.h

@@ -30,6 +30,8 @@ namespace qlow
 
         struct Statement;
         struct Expression;
+        
+        struct ThisExpression;
 
         struct DoEndBlock;
         struct IfElseBlock;
@@ -48,7 +50,8 @@ namespace qlow
         
         struct NewArrayExpression;
 
-        struct FeatureCallExpression;
+        struct MethodCallExpression;
+        struct FieldAccessExpression;
         
         struct IntConst;
     }
@@ -124,6 +127,7 @@ struct qlow::sem::Method : public SemanticObject
     std::vector<Variable*> arguments;
     std::string name;
     ast::MethodDefinition* astNode;
+    std::unique_ptr<ThisExpression> thisExpression;
     std::unique_ptr<DoEndBlock> body;
 
     LocalScope scope;
@@ -132,7 +136,8 @@ struct qlow::sem::Method : public SemanticObject
 
     inline Method(Scope& parentScope, std::shared_ptr<Type> returnType) :
         returnType{ std::move(returnType) },
-        scope{ parentScope },
+        scope{ parentScope, this },
+        thisExpression{ std::make_unique<ThisExpression>(this) },
         body{ nullptr }
     {
     }
@@ -140,7 +145,8 @@ struct qlow::sem::Method : public SemanticObject
     inline Method(ast::MethodDefinition* astNode, Scope& parentScope) :
         astNode{ astNode },
         name{ astNode->name },
-        scope{ parentScope },
+        scope{ parentScope, this },
+        thisExpression{ std::make_unique<ThisExpression>(this) },
         body{ nullptr }
     {
     }
@@ -149,6 +155,17 @@ struct qlow::sem::Method : public SemanticObject
 };
 
 
+struct qlow::sem::ThisExpression : public Variable
+{
+    Method* method;
+    inline ThisExpression(Method* method) :
+        Variable{ method->returnType, "this" },
+        method{ method}
+    {
+    }
+};
+
+
 struct qlow::sem::Statement : public SemanticObject, public Visitable<llvm::Value*, gen::FunctionGenerator, qlow::StatementVisitor>
 {
     virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) = 0;
@@ -160,7 +177,7 @@ struct qlow::sem::DoEndBlock : public Statement
     LocalScope scope;
     OwningList<Statement> statements;
 
-    inline DoEndBlock(Scope& parentScope) :
+    inline DoEndBlock(LocalScope& parentScope) :
         scope{ parentScope } {}
     
     virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override;
@@ -335,15 +352,35 @@ struct qlow::sem::UnaryOperation : public Operation
 };
 
 
-struct qlow::sem::FeatureCallExpression : public Expression
+struct qlow::sem::MethodCallExpression : public Expression
 {
     Method* callee;
     std::unique_ptr<Expression> target;
     OwningList<Expression> arguments;
     
-    inline FeatureCallExpression(std::unique_ptr<Expression> target,
+    inline MethodCallExpression(std::unique_ptr<Expression> target,
                                  Method* callee) :
-        Expression{ callee->returnType }
+        Expression{ callee->returnType },
+        callee{ callee }
+    {
+    }
+    
+    virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    
+    virtual std::string toString(void) const override;
+};
+
+
+struct qlow::sem::FieldAccessExpression : public Expression
+{
+    sem::Field* accessed;
+    std::unique_ptr<Expression> target;
+    OwningList<Expression> arguments;
+    
+    inline FieldAccessExpression(std::unique_ptr<Expression> target,
+                                 Field* accessed ) :
+        Expression{ accessed->type },
+        accessed{ accessed }
     {
     }
     
@@ -369,8 +406,8 @@ struct qlow::sem::IntConst : public Expression
 
 struct qlow::sem::FeatureCallStatement : public Statement 
 {
-    std::unique_ptr<FeatureCallExpression> expr;
-    inline FeatureCallStatement(std::unique_ptr<FeatureCallExpression> expr) :
+    std::unique_ptr<MethodCallExpression> expr;
+    inline FeatureCallStatement(std::unique_ptr<MethodCallExpression> expr) :
         expr{ std::move(expr) } {}
 
     virtual std::string toString(void) const override;

+ 3 - 1
src/Type.cpp

@@ -157,7 +157,7 @@ bool sem::NativeType::isIntegerType(void) const
 }
 
 
-llvm::Type* sem::NativeType::getLlvmType (llvm::LLVMContext& context) const
+llvm::Type* sem::NativeType::getLlvmType(llvm::LLVMContext& context) const
 {
     switch (type) {
         case VOID:
@@ -197,6 +197,8 @@ llvm::Type* sem::NativeType::getLlvmType (llvm::LLVMContext& context) const
             return llvm::Type::getDoubleTy(context);
         case FLOAT128:
             return llvm::Type::getFP128Ty(context);
+        default:
+            return nullptr;
     }
 }
 

+ 2 - 1
src/test.qlw

@@ -24,7 +24,8 @@ bignumbers do
     b: Int128
     c: Int64
 
-    //b := a + c
+    b := a + c as Int128
+    c := b as Int64
 end
 
 main2 do

+ 3 - 2
src/tests/structs.qlw

@@ -5,7 +5,8 @@ class Vec
     y: Integer
 
     yuhu: Integer do
-        return 5
+        x := 123
+        return x
     end
 end
 
@@ -15,7 +16,7 @@ main: Integer do
     value: Integer
     value := 5
 
-//    value := var.yuhu
+    value := var.yuhu
 //    var.x := 4
 //    var.hohoo := 4
     return value