Nicolas Winkler 6 年之前
父节点
当前提交
7c7471f628
共有 16 个文件被更改,包括 138 次插入1985 次删除
  1. 0 62
      src/Ast.cpp
  2. 0 569
      src/Ast.h
  3. 0 419
      src/AstVisitor.cpp
  4. 0 87
      src/AstVisitor.h
  5. 0 336
      src/CodeGeneration.cpp
  6. 0 57
      src/CodeGeneration.h
  7. 0 221
      src/Driver.cpp
  8. 0 52
      src/Driver.h
  9. 2 2
      src/Scope.cpp
  10. 60 32
      src/Scope.h
  11. 0 99
      src/main.cpp
  12. 2 2
      src/makefile
  13. 1 1
      src/sem/Context.h
  14. 3 4
      src/sem/Semantic.cpp
  15. 31 17
      src/sem/Semantic.h
  16. 39 25
      src/sem/Type.h

+ 0 - 62
src/Ast.cpp

@@ -1,62 +0,0 @@
-#include "Ast.h"
-#include "AstVisitor.h"
-#include "Semantic.h"
-
-#include <cstdlib>
-
-using namespace qlow::ast;
-
-
-AstObject::~AstObject(void)
-{
-}
-
-
-#define ACCEPT_DEFINITION(ClassName, Visitor) \
-std::unique_ptr<qlow::sem::SemanticObject> ClassName::accept(Visitor& v, sem::Scope& scope) \
-{ \
-    return v.visit(*this, scope); \
-}
-
-ACCEPT_DEFINITION(Class, StructureVisitor)
-ACCEPT_DEFINITION(FeatureDeclaration, StructureVisitor)
-ACCEPT_DEFINITION(FieldDeclaration, StructureVisitor)
-ACCEPT_DEFINITION(MethodDefinition, StructureVisitor)
-ACCEPT_DEFINITION(VariableDeclaration, StructureVisitor)
-
-ACCEPT_DEFINITION(Statement, StructureVisitor)
-ACCEPT_DEFINITION(DoEndBlock, StructureVisitor)
-ACCEPT_DEFINITION(IfElseBlock, StructureVisitor)
-ACCEPT_DEFINITION(WhileBlock, StructureVisitor)
-ACCEPT_DEFINITION(Expression, StructureVisitor)
-ACCEPT_DEFINITION(FeatureCall, StructureVisitor)
-ACCEPT_DEFINITION(AssignmentStatement, StructureVisitor)
-ACCEPT_DEFINITION(ReturnStatement, StructureVisitor)
-ACCEPT_DEFINITION(LocalVariableStatement, StructureVisitor)
-ACCEPT_DEFINITION(AddressExpression, StructureVisitor)
-ACCEPT_DEFINITION(IntConst, StructureVisitor)
-ACCEPT_DEFINITION(UnaryOperation, StructureVisitor)
-ACCEPT_DEFINITION(BinaryOperation, StructureVisitor)
-ACCEPT_DEFINITION(NewArrayExpression, StructureVisitor)
-ACCEPT_DEFINITION(CastExpression, StructureVisitor)
-
-
-Statement::~Statement(void)
-{
-}
-
-
-qlow::ast::IntConst::IntConst(std::string&& val, const qlow::CodePosition& p) :
-    AstObject{ p },
-    Expression{ p },
-    value{ strtoull(val.c_str(), nullptr, 0) }
-{
-}
-
-
-
-
-
-
-
-

+ 0 - 569
src/Ast.h

@@ -1,569 +0,0 @@
-// =============================================================================
-//
-// This file is part of the qlow compiler.
-//
-// Copyright (C) 2014-2015 Nicolas Winkler
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-// =============================================================================
-
-#ifndef QLOW_AST_H
-#define QLOW_AST_H
-
-#include <string>
-#include <vector>
-#include <memory>
-#include <utility>
-#include <map>
-
-#include "Visitor.h"
-#include "Util.h"
-#include "ErrorReporting.h"
-
-namespace qlow
-{
-    struct CodePosition;
-    
-    class StructureVisitor;
-    namespace ast
-    {
-        // base class
-        struct AstObject;
-
-        struct Class;
-
-        struct Type;
-        struct ClassType;
-        struct ArrayType;
-        struct PointerType;
-        
-        struct FeatureDeclaration;
-
-        struct FieldDeclaration;
-        struct MethodDefinition;
-
-        struct VariableDeclaration;
-        struct ArgumentDeclaration;
-
-        struct Statement;
-        
-        struct DoEndBlock;
-        struct IfElseBlock;
-        struct WhileBlock;
-
-        struct Expression;
-
-        struct FeatureCall;
-        struct AssignmentStatement;
-        struct ReturnStatement;
-        struct LocalVariableStatement;
-        struct AddressExpression;
-        struct IntConst;
-
-        struct Operation;
-        struct UnaryOperation;
-        struct BinaryOperation;
-        
-        struct NewArrayExpression;
-        
-        struct CastExpression;
-    }
-
-    namespace sem
-    {
-        struct SemanticObject;
-        struct Class;
-        
-        class Scope;
-
-//        template<typename T>
-//        using SymbolTable = std::map<std::string, std::unique_ptr<T>>;
-    }
-}
-
-
-
-struct qlow::ast::AstObject :
-    public Visitable<std::unique_ptr<sem::SemanticObject>, sem::Scope&, StructureVisitor>
-{
-    CodePosition pos;
-    
-    inline AstObject(const CodePosition& cp) :
-        pos{ cp } {}
-        
-    virtual ~AstObject(void);
-};
-
-
-struct qlow::ast::Class : public AstObject
-{
-    std::string name;
-    OwningList<FeatureDeclaration> features;
-    
-    inline Class(const std::string& name, OwningList<FeatureDeclaration>& features, const CodePosition& cp) :
-        AstObject{ cp },
-        name{ name }, features(std::move(features))
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&) override;
-};
-
-
-struct qlow::ast::Type : public AstObject
-{
-    inline Type(const CodePosition& cp) :
-        AstObject{ cp }
-    {
-    }
-    
-    virtual std::string asString(void) const = 0;
-    virtual inline std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&) override {}
-};
-
-
-struct qlow::ast::ClassType : public ast::Type
-{
-    std::string typeName;
-    
-    inline ClassType(const std::string& typeName, const CodePosition& cp) :
-        Type{ cp },
-        typeName{ typeName }
-    {
-    }
-    
-    inline ClassType(std::string&& typeName, const CodePosition& cp) :
-        Type{ cp },
-        typeName{ std::move(typeName) }
-    {
-    }
-    
-    inline std::string asString(void) const override { return typeName; }
-};
-
-
-struct qlow::ast::ArrayType : public ast::Type 
-{
-    std::unique_ptr<ast::Type> arrayType;
-    
-    inline ArrayType(std::unique_ptr<ast::Type> arrayType, const CodePosition& cp) :
-        Type{ cp },
-        arrayType{ std::move(arrayType) }
-    {
-    }
-    
-    inline std::string asString(void) const override {
-        return std::string("[") + arrayType->asString() + "]";
-    }
-};
-
-
-struct qlow::ast::PointerType : public ast::Type 
-{
-    std::unique_ptr<ast::Type> derefType;
-    
-    inline PointerType(std::unique_ptr<ast::Type> derefType, const CodePosition& cp) :
-        Type{ cp },
-        derefType{ std::move(derefType) }
-    {
-    }
-    
-    inline std::string asString(void) const override {
-        return derefType->asString() + "*";
-    }
-};
-
-
-struct qlow::ast::FeatureDeclaration : public AstObject
-{
-    std::string name;
-    std::unique_ptr<ast::Type> type;
-
-    inline FeatureDeclaration(std::unique_ptr<ast::Type> type, const std::string& name, const CodePosition& cp) :
-        AstObject{ cp },
-        name{ name },
-        type{ std::move(type) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::FieldDeclaration : public FeatureDeclaration
-{
-    inline FieldDeclaration(std::unique_ptr<ast::Type> type, const std::string& name, const CodePosition& cp) :
-        FeatureDeclaration{ std::move(type), name, cp }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::MethodDefinition : public FeatureDeclaration
-{
-    OwningList<ArgumentDeclaration> arguments;
-    
-    /// pointer to method body. If this is a null pointer, the method has only
-    /// been declared and not defined (with extern)
-    std::unique_ptr<DoEndBlock> body;
-
-    inline MethodDefinition(std::unique_ptr<ast::Type> type, const std::string& name,
-            std::unique_ptr<DoEndBlock> body, const CodePosition& cp) :
-        FeatureDeclaration{ std::move(type), name, cp },
-        body{ std::move(body) }
-    {
-    }
-
-
-    inline MethodDefinition(std::unique_ptr<ast::Type> type, const std::string& name,
-            OwningList<ArgumentDeclaration>&& arguments, std::unique_ptr<DoEndBlock> body, const CodePosition& cp) :
-        FeatureDeclaration{ std::move(type), name, cp },
-        arguments(std::move(arguments)),
-        body{ std::move(body) }
-    {
-    }
-
-    
-    inline MethodDefinition(std::unique_ptr<ast::Type> type, const std::string& name,
-            const CodePosition& cp) :
-        FeatureDeclaration{ std::move(type), name, cp },
-        body{ nullptr }
-    {
-    }
-    
-
-    inline MethodDefinition(std::unique_ptr<ast::Type> type, const std::string& name,
-            OwningList<ArgumentDeclaration>&& arguments, const CodePosition& cp) :
-        FeatureDeclaration{ std::move(type), name, cp },
-        arguments(std::move(arguments)),
-        body{ nullptr }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::VariableDeclaration : public AstObject
-{
-    std::unique_ptr<ast::Type> type;
-    std::string name;
-    inline VariableDeclaration(std::unique_ptr<ast::Type> type, std::string&& name, const CodePosition& cp) :
-        AstObject{ cp },
-        type{ std::move(type) },
-        name{ std::move(name) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::ArgumentDeclaration :
-    public VariableDeclaration
-{
-    inline ArgumentDeclaration(std::unique_ptr<ast::Type> type, std::string&& name, const CodePosition& cp) :
-        VariableDeclaration{ std::move(type), std::move(name), cp }
-    {
-    }
-
-    //virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::Statement : public virtual AstObject
-{
-    inline Statement(const CodePosition& cp) :
-        AstObject{ cp } {}
-        
-    virtual ~Statement(void);
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::DoEndBlock : public Statement 
-{
-    OwningList<Statement> statements;
-    
-    inline DoEndBlock(OwningList<Statement>&& statements, const CodePosition& cp) :
-        AstObject{ cp },
-        Statement{ cp },
-        statements(std::move(statements))
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::IfElseBlock : public Statement
-{
-    std::unique_ptr<Expression> condition;
-    std::unique_ptr<DoEndBlock> ifBlock;
-    std::unique_ptr<DoEndBlock> elseBlock;
-    
-    inline IfElseBlock(std::unique_ptr<Expression> condition,
-                       std::unique_ptr<DoEndBlock> ifBlock,
-                       std::unique_ptr<DoEndBlock> elseBlock,
-                       const CodePosition& cp) :
-        AstObject{ cp },
-        Statement{ cp },
-        condition{ std::move(condition) },
-        ifBlock{ std::move(ifBlock) },
-        elseBlock{ std::move(elseBlock) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::WhileBlock : public Statement
-{
-    std::unique_ptr<Expression> condition;
-    std::unique_ptr<DoEndBlock> body;
-    
-    inline WhileBlock(std::unique_ptr<Expression> condition,
-                      std::unique_ptr<DoEndBlock> body,
-                      const CodePosition& cp) :
-        AstObject{ cp },
-        Statement{ cp },
-        condition{ std::move(condition) },
-        body{ std::move(body) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::Expression : public virtual AstObject
-{
-    inline Expression(const CodePosition& cp) :
-        AstObject{ cp } {}
-        
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::FeatureCall : public Expression, public Statement
-{
-    std::unique_ptr<Expression> target;
-    std::string name;
-    OwningList<Expression> arguments;
-
-    inline FeatureCall(std::unique_ptr<Expression> target, const std::string& name, const CodePosition& cp) :
-        AstObject{ cp },
-        Expression{ cp }, Statement{ cp },
-        target(std::move(target)), name(name)
-    {
-    }
-
-
-    inline FeatureCall(std::unique_ptr<Expression> target, const std::string& name,
-            OwningList<Expression>&& arguments, const CodePosition& cp) :
-        AstObject{ cp },
-        Expression{ cp }, Statement{ cp },
-        target(std::move(target)), name(name), arguments(std::move(arguments))
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::ReturnStatement : public Statement
-{
-    std::unique_ptr<Expression> expr;
-
-    inline ReturnStatement(std::unique_ptr<Expression>&& expr, const CodePosition& cp) :
-        AstObject{ cp },
-        Statement{ cp },
-        expr{ std::move(expr) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::AssignmentStatement : public Statement
-{
-    std::unique_ptr<Expression> target;
-    std::unique_ptr<Expression> expr;
-
-    inline AssignmentStatement(std::unique_ptr<Expression>&& target, std::unique_ptr<Expression>&& expr, const CodePosition& cp) :
-        AstObject{ cp },
-        Statement{ cp },
-        target{ std::move(target) }, expr{ std::move(expr) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::LocalVariableStatement : public Statement
-{
-    std::string name;
-    std::unique_ptr<ast::Type> type;
-    inline LocalVariableStatement(std::string&& name, std::unique_ptr<Type> type, const CodePosition& cp) :
-        AstObject{ cp },
-        Statement{ cp },
-       name{ name },
-       type{ std::move(type) }
-    {
-    } 
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::AddressExpression : public Expression
-{
-    std::unique_ptr<Expression> target;
-    inline AddressExpression(std::unique_ptr<Expression> target,
-                             const CodePosition& cp) :
-        AstObject{ cp },
-        Expression{ cp },
-       target{ std::move(target) }
-    {
-    } 
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::IntConst : public Expression
-{
-    unsigned long long value;
-    
-    IntConst(unsigned long long v, const CodePosition& p) :
-        AstObject(p),
-        Expression(p),
-        value{ v } {}
-        
-    IntConst(std::string&& val, const CodePosition& p);
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::Operation : public Expression
-{
-    std::string opString;
-    CodePosition opPos;
-
-    inline Operation(const std::string& opString, const CodePosition& cp,
-                     const CodePosition& opPos) :
-        AstObject{ cp },
-        Expression{ cp },
-        opString{ opString },
-        opPos{ opPos }
-    {
-    }
-};
-
-
-struct qlow::ast::UnaryOperation : public Operation
-{
-    enum Side
-    {
-        PREFIX,
-        SUFFIX,
-    };
-
-    Side side;
-    std::unique_ptr<Expression> expr;
-
-    inline UnaryOperation(std::unique_ptr<Expression> expr, Side side,
-                          const std::string& op, const CodePosition& cp,
-                          const CodePosition& opPos
-                         ) :
-        AstObject{ cp },
-        Operation{ op, cp, opPos },
-        side{ side },
-        expr{ std::move(expr) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::BinaryOperation : public Operation
-{
-    std::unique_ptr<Expression> left;
-    std::unique_ptr<Expression> right;
-
-    inline BinaryOperation(std::unique_ptr<Expression> left,
-                           std::unique_ptr<Expression> right,
-                           const std::string& op,
-                           const CodePosition& cp,
-                           const CodePosition& opPos
-                          ) :
-        AstObject{ cp },
-        Operation{ op, cp, opPos },
-        left{ std::move(left) },
-        right{ std::move(right) }
-    {
-    }
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::NewArrayExpression : public Expression
-{
-    std::unique_ptr<ast::Type> type;
-    std::unique_ptr<Expression> length;
-    inline NewArrayExpression(std::unique_ptr<ast::Type> type,
-                              std::unique_ptr<Expression> length,
-                              const CodePosition& cp) :
-        AstObject{ cp },
-        Expression{ cp },
-        type{ std::move(type) },
-        length{ std::move(length) }
-    {
-    }
-    
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-struct qlow::ast::CastExpression : public Expression
-{
-    std::unique_ptr<ast::Expression> expression;
-    std::unique_ptr<ast::Type> targetType;
-    
-    inline CastExpression(std::unique_ptr<ast::Expression> expression,
-                          std::unique_ptr<ast::Type> targetType,
-                          const CodePosition& cp) :
-        AstObject{ cp },
-        Expression{ cp },
-        expression{ std::move(expression) },
-        targetType{ std::move(targetType) }
-    {
-    }
-    
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
-#endif // QLOW_AST_H
-
-

+ 0 - 419
src/AstVisitor.cpp

@@ -1,419 +0,0 @@
-#include "AstVisitor.h"
-#include "Ast.h"
-#include "ErrorReporting.h"
-
-#include <typeinfo>
-
-#include "Util.h"
-
-using namespace qlow;
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Class& ast, sem::Scope& scope)
-{
-    //auto c = std::make_unique<sem::Class>();
-    //c->name = ast.name;
-    //return c;
-    throw "shouldn't be called";
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureDeclaration& ast, sem::Scope& scope)
-{
-    // not needed, because 
-    throw "shouldn't be called";
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclaration& ast, sem::Scope& scope)
-{
-    auto f = std::make_unique<sem::Field>();
-    f->name = ast.name;
-    auto type = scope.getType(*ast.type);
-    if (type) {
-        f->type = type;
-    }
-    else {
-        throw SemanticError(SemanticError::UNKNOWN_TYPE,
-            ast.type->asString(),
-            ast.type->pos
-        );
-    }
-    return f;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope)
-{
-    auto returnType = scope.getType(*ast.type);
-    if (!returnType) {
-        throw SemanticError(SemanticError::UNKNOWN_TYPE,
-            ast.type->asString(),
-            ast.type->pos
-        );
-    }
-    auto m = std::make_unique<sem::Method>(scope, returnType);
-    m->name = ast.name;
-    m->astNode = &ast;
-    
-    for (auto& arg : ast.arguments) {
-        auto var = arg->accept(*this, scope);
-        if (dynamic_cast<sem::Variable*>(var.get())) {
-            std::unique_ptr<sem::Variable> variable =
-                unique_dynamic_cast<sem::Variable>(std::move(var));
-            variable->isParameter = true;
-            m->arguments.push_back(variable.get());
-            std::string varname = variable->name;
-            m->scope.putVariable(varname, std::move(variable));
-        }
-        else {
-            throw "internal error creating argument";
-        }
-    }
-    
-    return m;
-    //throw "  std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope) shouldn't be called";
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclaration& ast, sem::Scope& scope)
-{
-    auto v = std::make_unique<sem::Variable>();
-    v->name = ast.name;
-    auto type = scope.getType(*ast.type);
-    if (type) {
-        v->type = std::move(type);
-    }
-    else {
-        throw SemanticError(SemanticError::UNKNOWN_TYPE,
-            ast.type->asString(),
-            ast.type->pos
-        );
-    }
-    return v;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Statement& ast, sem::Scope& scope)
-{
-    printf("at: %d:%d to %d:%d\n", ast.pos.first_line, ast.pos.first_column, ast.pos.last_line, ast.pos.last_column);
-    printf("type: %s\n", typeid(ast).name());
-    throw "visit(Statement) shouldn't be called";
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& ast, sem::Scope& 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) {
-            auto type = body->scope.getType(*nvs->type);
-
-            if (!type)
-                throw SemanticError(SemanticError::UNKNOWN_TYPE,
-                                    nvs->type->asString(),
-                                    nvs->type->pos);
-            auto var = std::make_unique<sem::Variable>(std::move(type), nvs->name);
-            body->scope.putVariable(nvs->name, std::move(var));
-            continue;
-        }
-        
-        auto v = statement->accept(*this, body->scope);
-        if (dynamic_cast<sem::MethodCallExpression*>(v.get()) != nullptr) {
-            body->statements.push_back(
-                std::make_unique<sem::FeatureCallStatement>(
-                unique_dynamic_cast<sem::MethodCallExpression>(std::move(v))));
-        }
-        else {
-            body->statements.push_back(unique_dynamic_cast<sem::Statement>(std::move(v)));
-        }
-    }
-    return body;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IfElseBlock& ast, sem::Scope& scope)
-{
-    auto condition = ast.condition->accept(*this, scope);
-    auto ifB = ast.ifBlock->accept(*this, scope);
-    auto eB= ast.elseBlock->accept(*this, scope);
-    
-    if (!dynamic_cast<sem::DoEndBlock*>(ifB.get())
-        || !dynamic_cast<sem::DoEndBlock*>(eB.get())
-        || !dynamic_cast<sem::Expression*>(condition.get()))
-        throw "internal error, invalid if block";
-    
-    auto condExpr = unique_dynamic_cast<sem::Expression>(std::move(condition));
-    auto ifBBlock = unique_dynamic_cast<sem::DoEndBlock>(std::move(ifB));
-    auto eBBlock= unique_dynamic_cast<sem::DoEndBlock>(std::move(eB));
-    
-    auto ieb = std::make_unique<sem::IfElseBlock>(std::move(condExpr), std::move(ifBBlock), std::move(eBBlock));
-    
-    return ieb;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::WhileBlock& ast, sem::Scope& scope)
-{
-    auto condition = ast.condition->accept(*this, scope);
-    auto body = ast.body->accept(*this, scope);
-    
-    if (!dynamic_cast<sem::DoEndBlock*>(body.get()) ||
-        !dynamic_cast<sem::Expression*>(condition.get()))
-        throw "internal error, invalid while block";
-    
-    auto condExpr = unique_dynamic_cast<sem::Expression>(std::move(condition));
-    auto bodyblock = unique_dynamic_cast<sem::DoEndBlock>(std::move(body));
-    
-    auto wb = std::make_unique<sem::WhileBlock>(std::move(condExpr), std::move(bodyblock));
-    
-    return wb;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& ast, sem::Scope& scope)
-{
-    throw "visit(Expression) shouldn't be called";
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope)
-{
-    std::unique_ptr<sem::Expression> target = nullptr;
-    if (ast.target) {
-        target = unique_dynamic_cast<sem::Expression>(
-            ast.target->accept(*this, scope));
-    }
-    
-    sem::Method* method;
-    sem::Variable* var;
-    
-    if (target) {
-        method = target->type->getScope().getMethod(ast.name);
-        var = target->type->getScope().getVariable(ast.name);
-    }
-    else {
-        method = scope.getMethod(ast.name);
-        var = scope.getVariable(ast.name);
-    }
-    
-    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::MethodCallExpression>(
-                std::move(target), method);
-    
-            if (ast.arguments.size() != method->arguments.size())
-                throw SemanticError(SemanticError::WRONG_NUMBER_OF_ARGUMENTS, ast.name, ast.pos);
-            for (size_t i = 0; i < ast.arguments.size(); i++) {
-                auto& arg = ast.arguments[i];
-                auto& argTypeShouldHave = method->arguments[i]->type;
-                auto argument = arg->accept(*this, scope);
-                if (sem::Expression* expr =
-                        dynamic_cast<sem::Expression*>(argument.get()); expr) {
-                    if (!expr->type->equals(*argTypeShouldHave))
-                        throw SemanticError(SemanticError::TYPE_MISMATCH,
-                            "argument passed to function has wrong type: '" +
-                            expr->type->asString() + "' instead of '" +
-                            argTypeShouldHave->asString() + "'",
-                            arg->pos
-                        );
-                    fce->arguments.push_back(
-                        unique_dynamic_cast<sem::Expression>(std::move(argument)));
-                }
-                else {
-                    throw "internal error: non-expression passed as function parameter";
-                }
-            }
-            return fce;
-        }
-        else {
-            throw SemanticError(SemanticError::FEATURE_NOT_FOUND, ast.name, ast.pos);
-        }
-    }
-    else if (var) {
-        if (sem::Field* field = dynamic_cast<sem::Field*>(var); field) {
-            auto* thisExpr = scope.getVariable("this");
-            if (!thisExpr)
-                throw "no this found";
-            Logger::getInstance().debug() << "feature call " << var->toString() << " is a field\n";
-            return std::make_unique<sem::FieldAccessExpression>(std::make_unique<sem::LocalVariableExpression>(thisExpr), field);
-        }
-        else {
-            Logger::getInstance().debug() << "feature call " << var->toString() << " is not a field\n";
-            return std::make_unique<sem::LocalVariableExpression>(var);
-        }
-    }
-    else if (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())) {
-                fce->arguments.push_back(unique_dynamic_cast<sem::Expression>(std::move(argument)));
-            }
-            else {
-                throw "internal error: non-expression passed as function parameter";
-            }
-        }
-        fce->callee = method;
-        return fce;
-    }
-    else {
-#ifdef DEBUGGING
-        printf("var not found: %s\n", ast.name.c_str());
-        printf("current scope: %s\n", scope.toString().c_str());
-#endif
-        throw SemanticError(SemanticError::FEATURE_NOT_FOUND, ast.name, ast.pos);
-    }
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::AssignmentStatement& ast, sem::Scope& scope)
-{
-    auto as = std::make_unique<sem::AssignmentStatement>();
-    
-//    as->value = unique_dynamic_cast<sem::Expression>(visit(*ast.expr, classes));
-//    as->target = unique_dynamic_cast<sem::Expression>(visit(*ast.target, classes));
-    as->value = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
-    as->target = unique_dynamic_cast<sem::Expression>(ast.target->accept(*this, scope));
-    
-    if (as->target->type->equals(*as->value->type)) {
-        return as;
-    }
-    else {
-        throw SemanticError(
-            SemanticError::TYPE_MISMATCH,
-            "Can't assign expression of type '" + as->value->type->asString() +
-            "' to value of type '" + as->target->type->asString() + "'.",
-            ast.pos
-        );
-    }
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ReturnStatement& ast, sem::Scope& scope)
-{
-    auto shouldReturn = scope.getReturnableType();
-    
-    if (shouldReturn == nullptr) {
-        if (ast.expr == nullptr)
-            return std::make_unique<sem::ReturnStatement>();
-        else
-            throw SemanticError(
-                SemanticError::INVALID_RETURN_TYPE,
-                "This method should not return any value.",
-                ast.expr->pos
-            );
-    }
-    else if (ast.expr == nullptr) {
-        throw SemanticError(
-            SemanticError::INVALID_RETURN_TYPE,
-            "This method should return a value.",
-            ast.pos
-        );
-    }
-    
-    auto returnValue = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
-    
-    if (!shouldReturn->equals(*returnValue->type)) {
-        throw SemanticError(
-            SemanticError::INVALID_RETURN_TYPE,
-            "return value must be of type '" + shouldReturn->asString() + "' (not '" +
-            returnValue->type->asString() + "')",
-            ast.expr->pos
-        );
-    }
-    
-    auto as = std::make_unique<sem::ReturnStatement>();
-    as->value = std::move(returnValue);
-    return as;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::LocalVariableStatement& ast, sem::Scope& scope)
-{
-    throw "shouldn't be called";
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(
-    ast::AddressExpression& ast, sem::Scope& scope)
-{
-    auto target = unique_dynamic_cast<sem::Expression>(ast.target->accept(*this, scope));
-    auto& targetType = target->type;
-    
-    if (!target->isLValue()) {
-        throw NotLValue(targetType->asString(), ast.pos);
-    }
-    
-    return std::make_unique<sem::AddressExpression>(std::move(target));
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IntConst& ast, sem::Scope& scope)
-{
-    return std::make_unique<sem::IntConst>(ast.value);
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::UnaryOperation& ast, sem::Scope& scope)
-{
-    auto argument = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
-    auto ret = std::make_unique<sem::UnaryOperation>(argument->type);
-            // TODO not a feasible assumption
-    ret->opString = ast.opString;
-    ret->side = ast.side;
-    ret->arg = std::move(argument);
-    return ret;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperation& ast, sem::Scope& scope)
-{
-    auto leftEval = unique_dynamic_cast<sem::Expression>(ast.left->accept(*this, scope));
-    auto rightEval = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
-    
-    sem::Method* operationMethod = leftEval->type->getScope().resolveMethod(
-        ast.opString, { rightEval->type }
-    );
-    
-    Logger::getInstance().debug() << "looked for operation method for operator " <<
-    ast.opString << std::endl;
-    if (!operationMethod) {
-        throw SemanticError(SemanticError::OPERATOR_NOT_FOUND,
-            "operator " + ast.opString + " not found for types '" +
-            leftEval->type->asString() + "' and '" + rightEval->type->asString() + "'",
-            ast.opPos);
-    }
-    
-    auto ret = std::make_unique<sem::BinaryOperation>(leftEval->type, &ast);
-    
-    ret->operationMethod = operationMethod;
-    ret->opString = ast.opString;
-    ret->left = std::move(leftEval);
-    ret->right = std::move(rightEval);
-    return ret;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewArrayExpression& ast, sem::Scope& scope)
-{
-    auto ret = std::make_unique<sem::NewArrayExpression>(scope.getType(*ast.type));
-    return ret;
-}
-
-
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::CastExpression& ast, sem::Scope& scope)
-{
-    auto expr = unique_dynamic_cast<sem::Expression>(ast.expression->accept(*this, scope));
-    auto type = scope.getType(*ast.targetType);
-    return std::make_unique<sem::CastExpression>(
-        std::move(expr), std::move(type), &ast);
-}
-

+ 0 - 87
src/AstVisitor.h

@@ -1,87 +0,0 @@
-#ifndef QLOW_AST_VISITOR_H
-#define QLOW_AST_VISITOR_H
-
-#include "Visitor.h"
-#include "Ast.h"
-#include "Semantic.h"
-#include "Builtin.h"
-#include "Scope.h"
-
-
-#include <memory>
-
-
-namespace qlow
-{
-    namespace ast
-    {
-        template<typename T>
-        using List = std::vector<std::unique_ptr<T>>;
-    }
-}
-
-
-namespace qlow
-{
-    class StructureVisitor;
-}
-
-
-class qlow::StructureVisitor :
-    public Visitor<
-        std::unique_ptr<sem::SemanticObject>,
-        sem::Scope&,
-
-        ast::Class,
-        ast::FeatureDeclaration,
-        ast::FieldDeclaration,
-        ast::MethodDefinition,
-        ast::VariableDeclaration,
-        ast::Statement,
-        ast::DoEndBlock,
-        ast::IfElseBlock,
-        ast::WhileBlock,
-        ast::Expression,
-        ast::FeatureCall,
-        ast::AssignmentStatement,
-        ast::ReturnStatement,
-        ast::LocalVariableStatement,
-        ast::AddressExpression,
-        ast::IntConst,
-        ast::UnaryOperation,
-        ast::BinaryOperation,
-        ast::NewArrayExpression,
-        ast::CastExpression
-    >
-{
-public:
-    using ReturnType = std::unique_ptr<sem::SemanticObject>;
-
-    ReturnType visit(ast::Class& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::FeatureDeclaration& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::FieldDeclaration& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::MethodDefinition& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::VariableDeclaration& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::Statement& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::DoEndBlock& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::IfElseBlock& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::WhileBlock& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::Expression& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::FeatureCall& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::AssignmentStatement& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::ReturnStatement& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::LocalVariableStatement& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::AddressExpression& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::IntConst& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::UnaryOperation& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::BinaryOperation& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::NewArrayExpression& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::CastExpression& ast, sem::Scope& scope) override;
-};
-
-
-
-
-#endif // QLOW_AST_VISITOR_H
-
-

+ 0 - 336
src/CodeGeneration.cpp

@@ -1,336 +0,0 @@
-#include "CodeGeneration.h"
-
-#include <llvm/IR/LLVMContext.h>
-#include <llvm/IR/LegacyPassManager.h>
-#include <llvm/Transforms/IPO/PassManagerBuilder.h>
-#include <llvm/IR/Type.h>
-#include <llvm/IR/DerivedTypes.h>
-#include <llvm/IR/Constants.h>
-#include <llvm/IR/BasicBlock.h>
-#include <llvm/IR/Verifier.h>
-#include <llvm/IR/IRBuilder.h>
-#include <llvm/IR/Attributes.h>
-#include <llvm/Target/TargetMachine.h>
-#include <llvm/Support/TargetRegistry.h>
-#include <llvm/Support/TargetSelect.h>
-#include <llvm/Support/FileSystem.h>
-#include <llvm/Support/raw_os_ostream.h>
-
-
-using namespace qlow;
-
-static llvm::LLVMContext context;
-
-namespace qlow
-{
-namespace gen
-{
-
-std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
-{
-    using llvm::Module;
-    using llvm::Function;
-    using llvm::Argument;
-    using llvm::Type;
-    using llvm::FunctionType;
-    using llvm::BasicBlock;
-    using llvm::Value;
-    using llvm::IRBuilder;
-    
-    Logger& logger = Logger::getInstance();
-    
-#ifdef DEBUGGING
-        printf("creating llvm module\n"); 
-#endif 
-
-    std::unique_ptr<Module> module = llvm::make_unique<Module>("qlow_module", context);
-
-    // create llvm structs
-    // TODO implement detection of circles
-    for (auto& [name, cl] : objects.classes) {
-        llvm::StructType* st;
-        std::vector<llvm::Type*> fields;
-#ifdef DEBUGGING
-        printf("creating llvm struct for %s\n", name.c_str());
-#endif
-        int llvmStructIndex = 0;
-        for (auto& [name, field] : cl->fields) {
-            field->llvmStructIndex = llvmStructIndex;
-            fields.push_back(field->type->getLlvmType(context));
-            if (fields[fields.size() - 1] == nullptr)
-                throw "internal error: possible circular dependency";
-            
-            llvmStructIndex++;
-        }
-        st = llvm::StructType::create(context, fields, name);
-        cl->llvmType = st;
-    }
-    
-    llvm::AttrBuilder ab;
-    ab.addAttribute(llvm::Attribute::AttrKind::NoInline);
-    ab.addAttribute(llvm::Attribute::AttrKind::NoUnwind);
-    //ab.addAttribute(llvm::Attribute::AttrKind::OptimizeNone);
-    //ab.addAttribute(llvm::Attribute::AttrKind::UWTable);
-    ab.addAttribute("no-frame-pointer-elim", "true");
-    ab.addAttribute("no-frame-pointer-elim-non-leaf");
-    llvm::AttributeSet as = llvm::AttributeSet::get(context, ab);
-    
-    
-    std::vector<llvm::Function*> functions;
-    auto verifyStream = llvm::raw_os_ostream(logger.debug());
-    
-    // create all llvm functions
-    for (auto& [name, cl] : objects.classes) {
-        for (auto& [name, method] : cl->methods) {
-            Function* func = generateFunction(module.get(), method.get());
-            for (auto a : as) {
-                func->addFnAttr(a);
-            }
-            functions.push_back(func);
-        }
-    }
-    
-    for (auto& [name, method] : objects.functions) {
-        Function* func = generateFunction(module.get(), method.get());
-        for (auto a : as) {
-            func->addFnAttr(a);
-        }
-        functions.push_back(func);
-    }
-
-    for (auto& [name, cl] : objects.classes){
-        for (auto& [name, method] : cl->methods) {
-            if (!method->body)
-                continue;
-            
-            FunctionGenerator fg(*method, module.get(), as);
-            Function* f = fg.generate();
-            logger.debug() << "verifying function: " << method->name << std::endl;
-            bool corrupt = llvm::verifyFunction(*f, &verifyStream);
-            if (corrupt) {
-                module->print(verifyStream, nullptr);
-                throw "corrupt llvm function";
-            }
-#ifdef DEBUGGING
-            printf("verified function: %s\n", method->name.c_str());
-#endif
-        }
-    }
-    for (auto& [name, method] : objects.functions) {
-        if (!method->body)
-            continue;
-        
-        FunctionGenerator fg(*method, module.get(), as);
-        Function* f = fg.generate();
-        logger.debug() << "verifying function: " << method->name << std::endl;
-        bool corrupt = llvm::verifyFunction(*f, &verifyStream);
-        if (corrupt) {
-            module->print(verifyStream, nullptr);
-            throw "corrupt llvm function";
-        }
-#ifdef DEBUGGING
-        printf("verified function: %s\n", method->name.c_str());
-#endif
-    }
-    return module;
-}
-
-
-llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
-{
-    using llvm::Function;
-    using llvm::Argument;
-    using llvm::Type;
-    using llvm::FunctionType;
-    
-    Type* returnType;
-    if (method->returnType)
-        returnType = method->returnType->getLlvmType(context);
-    else
-        returnType = llvm::Type::getVoidTy(context);
-    
-    std::vector<Type*> argumentTypes;
-    if (method->thisExpression != nullptr) {
-        Type* enclosingType = method->thisExpression->type->getLlvmType(context);
-        argumentTypes.push_back(enclosingType);
-    }
-    
-    for (auto& arg : method->arguments) {
-        Type* argumentType = arg->type->getLlvmType(context);
-        argumentTypes.push_back(argumentType);
-    }
-    
-    FunctionType* funcType = FunctionType::get(
-        returnType, argumentTypes, false);
-#ifdef DEBUGGING
-    printf("looking up llvm type of %s\n", method->name.c_str());
-#endif 
-    if (returnType == nullptr)
-        throw "invalid return type";
-    Function* func = Function::Create(funcType, Function::ExternalLinkage, method->name, module);
-    method->llvmNode = func;
-    
-    // linking alloca instances for funcs
-    auto argIterator = func->arg_begin();
-    if (method->thisExpression != nullptr) {
-        method->thisExpression->allocaInst = &*argIterator;
-        Logger::getInstance().debug() << "allocaInst of this";
-        argIterator++;
-    }
-    
-    size_t argIndex = 0;
-    for (; argIterator != func->arg_end(); argIterator++) {
-        if (argIndex > method->arguments.size())
-            throw "internal error";
-        method->arguments[argIndex]->allocaInst = &*argIterator;
-#ifdef DEBUGGING
-        printf("allocaInst of arg '%s': %p\n", method->arguments[argIndex]->name.c_str(), method->arguments[argIndex]->allocaInst);
-#endif 
-        argIndex++;
-    }
-    
-    //printf("UEEEEEEEE %s\n", method->name.c_str());
-    return func;
-}
-
-
-void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
-{
-    using llvm::legacy::PassManager;
-    using llvm::PassManagerBuilder;
-    using llvm::raw_fd_ostream;
-    using llvm::Target;
-    using llvm::TargetMachine;
-    using llvm::TargetRegistry;
-    using llvm::TargetOptions;
-
-    Logger& logger = Logger::getInstance();
-    logger.debug() << "verifying mod" << std::endl;
-    auto ostr = llvm::raw_os_ostream(logger.debug());
-#ifdef DEBUGGING
-    module->print(ostr, nullptr);
-#endif
-    bool broken = llvm::verifyModule(*module);
-    
-    if (broken)
-        throw "invalid llvm module";
-    
-    logger.debug() << "mod verified" << std::endl;
-
-    llvm::InitializeAllTargetInfos();
-    llvm::InitializeAllTargets();
-    llvm::InitializeAllTargetMCs();
-    llvm::InitializeAllAsmParsers();
-    llvm::InitializeAllAsmPrinters();
-
-    PassManager pm;
-    
-    int sizeLevel = 0;
-    PassManagerBuilder builder;
-    builder.OptLevel = optLevel;
-    builder.SizeLevel = sizeLevel;
-    if (optLevel >= 2) {
-        builder.DisableUnitAtATime = false;
-        builder.DisableUnrollLoops = false;
-        builder.LoopVectorize = true;
-        builder.SLPVectorize = true;
-    }
-
-    builder.populateModulePassManager(pm);
-
-    const char cpu[] = "generic";
-    const char features[] = "";
-
-    std::string error;
-    std::string targetTriple = llvm::sys::getDefaultTargetTriple();
-    const Target* target = TargetRegistry::lookupTarget(targetTriple, error);
-
-    if (!target) {
-        logger.debug() << "could not create target: " << error << std::endl;
-        throw "internal error";
-    }
-
-    TargetOptions targetOptions;
-    auto relocModel = llvm::Optional<llvm::Reloc::Model>(llvm::Reloc::Model::PIC_);
-    std::unique_ptr<TargetMachine> targetMachine(
-        target->createTargetMachine(targetTriple, cpu,
-            features, targetOptions, relocModel));
-
-    std::error_code errorCode;
-    raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
-    targetMachine->addPassesToEmitFile(pm, dest,
-//        llvm::LLVMTargetMachine::CGFT_ObjectFile,
-        llvm::TargetMachine::CGFT_ObjectFile);
-
-    pm.run(*module);
-    dest.flush();
-    dest.close();
-
-    return;
-}
-
-} // namespace gen
-} // namespace qlow
-
-
-llvm::Function* qlow::gen::FunctionGenerator::generate(void)
-{
-    using llvm::Function;
-    using llvm::Argument;
-    using llvm::Type;
-    using llvm::FunctionType;
-    using llvm::BasicBlock;
-    using llvm::Value;
-    using llvm::IRBuilder;
-    
-#ifdef DEBUGGING
-    printf("generate function %s\n", method.name.c_str()); 
-#endif
-
-    Function* func = module->getFunction(method.name);
-
-    if (func == nullptr) {
-        throw "internal error: function not found";
-    }
-
-    BasicBlock* bb = BasicBlock::Create(context, "entry", func);
-
-    pushBlock(bb);
-
-    IRBuilder<> builder(context);
-    builder.SetInsertPoint(bb);
-    for (auto& [name, var] : method.body->scope.getLocals()) {
-        if (var.get() == nullptr)
-            throw "wtf null variable";
-        if (var->type == nullptr)
-            throw "wtf null type";
-        
-        llvm::AllocaInst* v = builder.CreateAlloca(var->type->getLlvmType(context));
-        var->allocaInst = v;
-    }
-    
-    for (auto& statement : method.body->statements) {
-#ifdef DEBUGGING
-        printf("statement visit %s\n", statement->toString().c_str());
-#endif
-        statement->accept(statementVisitor, *this);
-    }
-    
-
-#ifdef DEBUGGING
-    printf("End of Function\n");
-#endif
-    
-    //Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
-    
-    builder.SetInsertPoint(getCurrentBlock());
-    if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
-        if (!getCurrentBlock()->getTerminator())
-            builder.CreateRetVoid();
-    }
-
-    return func;
-}
-
-
-

+ 0 - 57
src/CodeGeneration.h

@@ -1,57 +0,0 @@
-#ifndef QLOW_CODE_GENERATION_H
-#define QLOW_CODE_GENERATION_H
-
-#include "Semantic.h"
-#include "Builtin.h"
-#include "CodegenVisitor.h"
-
-#include <stack>
-
-#include <llvm/IR/Module.h>
-
-namespace qlow
-{
-namespace gen
-{
-    std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects);
-    llvm::Function* generateFunction (llvm::Module* module, sem::Method* method);
-    void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module, int optLevel);
-
-    class FunctionGenerator;
-}
-}
-
-class qlow::gen::FunctionGenerator
-{
-    const sem::Method& method;
-    llvm::Module* module;
-    llvm::AttributeSet& attributes;
-
-    std::stack<llvm::BasicBlock*> basicBlocks;
-
-public:
-
-    StatementVisitor statementVisitor;
-    ExpressionCodegenVisitor expressionVisitor;
-    LValueVisitor lvalueVisitor;
-
-    inline FunctionGenerator(const sem::Method& m, llvm::Module* module,
-        llvm::AttributeSet& attributes) :
-        method{ m },
-        module{ module },
-        attributes{ attributes },
-        expressionVisitor{ *this }
-    {
-    }
-
-    llvm::Function* generate(void);
-
-    inline llvm::Module* getModule(void) const { return module; }
-    inline llvm::LLVMContext& getContext(void) const { return module->getContext(); }
-    inline llvm::BasicBlock* getCurrentBlock(void) const { return basicBlocks.top(); }
-    inline void pushBlock(llvm::BasicBlock* bb) { basicBlocks.push(bb); }
-    inline llvm::BasicBlock* popBlock(void) { auto* bb = basicBlocks.top(); basicBlocks.pop(); return bb; }
-};
-
-
-#endif // QLOW_CODE_GENERATION_H

+ 0 - 221
src/Driver.cpp

@@ -1,221 +0,0 @@
-#include "Driver.h"
-
-#include "Ast.h"
-#include "Semantic.h"
-#include "Builtin.h"
-#include "CodeGeneration.h"
-
-#include "Logging.h"
-
-#include <cstdio>
-
-extern std::unique_ptr<std::vector<std::unique_ptr<qlow::ast::AstObject>>> parsedClasses;
-extern FILE* qlow_parser_in;
-extern int qlow_parser_parse(void);
-extern const char* qlow_parser_filename;
-
-using namespace qlow;
-
-Options Options::parseOptions(int argc, char** argv)
-{
-    static const std::map<std::string, bool Options::*> boolArgs = 
-    {
-        {"-S",              &Options::emitAssembly},
-        {"--emit-assembly", &Options::emitAssembly},
-        {"-L",              &Options::emitLlvm},
-        {"--emit-llvm",     &Options::emitLlvm},
-    };
-    
-    Options options{};
-    
-    for (int i = 1; i < argc; i++) {
-        std::string arg = argv[i];
-        if (boolArgs.find(arg) != boolArgs.end()) {
-            bool Options::* attr = boolArgs.find(arg)->second;
-            options.*attr = true;
-        }
-        else if (arg == "-o" || arg == "--out") {
-            if (argc > i + 1) {
-                options.outfile = argv[++i];
-            }
-            else {
-                throw "Please specify a filename after '-o'";
-            }
-        }
-        else if (arg.rfind("-O", 0) == 0) {
-            if (arg.size() > 2) {
-                options.optLevel = std::stoi(arg.substr(2));
-            }
-            else {
-                options.optLevel = 2;
-            }
-        }
-        else {
-            if (options.outfile == "")
-                options.outfile = arg + ".o";
-            options.infiles.push_back(std::move(arg));
-        }
-    }
-    if (options.outfile == "")
-        options.outfile = "a.out";
-    return options;
-}
-
-
-Driver::Driver(int argc, char** argv) :
-    options{ Options::parseOptions(argc, argv) }
-{
-}
-
-
-int Driver::run(void)
-{
-    Logger& logger = Logger::getInstance();
-    
-    logger.debug() << "starting parser" << std::endl;
-    //logger.logError("driver not yet implemented", {options.emitAssembly ? "asm" : "noasm", 10, 11, 12, 13});
-    
-    std::vector<std::unique_ptr<qlow::ast::AstObject>> objects;
-    bool errorOccurred = false;
-    
-    for (auto& filename : options.infiles) {
-        std::FILE* file = std::fopen(filename.c_str(), "r");
-        ::qlow_parser_filename = filename.c_str();
-        
-        try {
-            auto newObjects = parseFile(file);
-            objects.insert(objects.end(),
-                           std::make_move_iterator(newObjects.begin()),
-                           std::make_move_iterator(newObjects.end()));
-        }
-        catch (const CompileError& ce) {
-            ce.print(logger);
-            errorOccurred = true;
-        }
-        catch (const char* errMsg) {
-            reportError(errMsg);
-            errorOccurred = true;
-        }
-        catch (...) {
-            reportError("an unknown error occurred.");
-            errorOccurred = true;
-        }
-        
-        if (file)
-            std::fclose(file);
-    }
-    
-    if (errorOccurred) {
-        logger << "Aborting due to syntax errors." << std::endl;
-        return 1;
-    }
-    
-    std::unique_ptr<qlow::sem::GlobalScope> semClasses = nullptr;
-    try {
-        semClasses =
-            qlow::sem::createFromAst(objects);
-    }
-    catch(SemanticError& se) {
-        se.print(logger);
-        errorOccurred = true;
-    }
-    catch(const char* err) {
-        reportError(err);
-        errorOccurred = true;
-    }
-    catch (...) {
-        reportError("an unknown error occurred.");
-        errorOccurred = true;
-    }
-    
-    if (errorOccurred) {
-        logger << "Aborting due to semantic errors." << std::endl;
-        return 1;
-    }
-    
-
-    for (auto& [a, b] : semClasses->classes) {
-        logger.debug() << a << ": " << b->toString() << std::endl;
-    }
-    
-    
-
-    /*auto main = semClasses->classes.find("Main");
-    qlow::sem::Class* mainClass = nullptr;
-    if (main == semClasses->classes.end()) {
-        logger.logError("No Main class found");
-        return 1;
-    }
-    else {
-        mainClass = main->second.get();
-    }*/
-    
-    auto* mainMethod = semClasses->getMethod("main");
-    if (mainMethod == nullptr && false) {
-        // TODO handle main ckeck well
-        logger.logError("no main method found");
-        return 1;
-    }
-    
-    logger.debug() << "starting code generation!" << std::endl;
-
-    std::unique_ptr<llvm::Module> mod = nullptr;
-    
-    try {
-        mod = qlow::gen::generateModule(*semClasses);
-    }
-    catch (const char* err) {
-        reportError(err);
-        return 1;
-    }
-    catch (SemanticError& err) {
-        err.print(logger);
-        return 1;
-    }
-    catch (...) {
-        reportError("unknown error during code generation");
-        return 1;
-    }
-    
-    try {
-        qlow::gen::generateObjectFile(options.outfile, std::move(mod), options.optLevel);
-    }
-    catch (const char* msg) {
-        logger.logError(msg);
-        return 1;
-    }
-    catch (...) {
-        logger.logError("unknown error during object file creation");
-        reportError("unknown error during object file creation");
-        return 1;
-    }
-    
-    logger.debug() << "object exported!" << std::endl;
-    
-    return 0;
-}
-
-
-std::vector<std::unique_ptr<qlow::ast::AstObject>> Driver::parseFile(FILE* file)
-{
-    ::qlow_parser_in = file;
-    if (!::qlow_parser_in)
-        throw "Could not run parser: Invalid file";
-    
-    ::qlow_parser_parse();
-    
-    auto retval = std::move(*parsedClasses);
-    parsedClasses.reset();
-    return retval;
-}
-
-
-
-
-
-
-
-
-
-
-

+ 0 - 52
src/Driver.h

@@ -1,52 +0,0 @@
-#ifndef QLOW_DRIVER_H
-#define QLOW_DRIVER_H
-
-#include <vector>
-#include <optional>
-#include <memory>
-#include <string>
-#include <utility>
-
-namespace qlow
-{
-    struct Options;
-    
-    class Driver;
-    
-    
-    namespace ast
-    {
-        struct AstObject;
-    }
-}
-
-
-struct qlow::Options
-{
-    bool emitAssembly;
-    bool emitLlvm;
-    std::string outfile = "a.out";
-    std::vector<std::string> infiles;
-    
-    int optLevel = 0;
-    
-    static Options parseOptions(int argc, char** argv);
-};
-
-
-class qlow::Driver
-{
-    Options options;
-public:
-    Driver(void) = delete;
-    Driver(int argc, char** argv);
-    
-    int run(void);
-    
-    /// \brief runs the parser over a given stream
-    /// \warning Don't call concurrently. Not (yet) supported!
-    std::vector<std::unique_ptr<qlow::ast::AstObject>> parseFile(FILE* file);
-};
-
-
-#endif // QLOW_DRIVER_H

+ 2 - 2
src/Scope.cpp

@@ -12,7 +12,7 @@ sem::Scope::~Scope(void)
 
 
 sem::Method* sem::Scope::resolveMethod(const std::string& name,
-    const std::vector<std::shared_ptr<Type>> argumentTypes)
+    const std::vector<TypeId> argumentTypes)
 {
     sem::Method* m = getMethod(name);
     if (!m)
@@ -45,7 +45,7 @@ sem::Method* sem::GlobalScope::getMethod(const std::string& name)
 }
 
 
-std::shared_ptr<sem::Type> sem::GlobalScope::getType(const ast::Type& name)
+qlow::sem::TypeId sem::GlobalScope::getType(const ast::Type& name)
 {
     if (const auto* arr = dynamic_cast<const ast::ArrayType*>(&name); arr) {
         return std::make_shared<sem::ArrayType>(getType(*arr->arrayType));

+ 60 - 32
src/Scope.h

@@ -8,6 +8,8 @@
 #include <llvm/IR/Type.h>
 #include <llvm/IR/Value.h>
 
+#include "Util.h"
+
 namespace qlow
 {
     namespace ast
@@ -23,7 +25,7 @@ namespace qlow
         template<typename T>
         using SymbolTable = std::map<std::string, std::unique_ptr<T>>;
 
-
+        class Semantic;
         struct Class;
         struct Method;
         struct Variable;
@@ -38,6 +40,8 @@ namespace qlow
         class NativeTypeScope;
         
         class Type;
+        using TypeId = size_t;
+
         class NativeType;
     }
 }
@@ -45,16 +49,25 @@ namespace qlow
 
 class qlow::sem::Scope
 {
+protected:
+    const Semantic& semantic;
 public:
+    inline Scope(const Semantic& semantic) :
+        semantic{ semantic }
+    {
+    }
+
     virtual ~Scope(void);
     virtual Variable* getVariable(const std::string& name) = 0;
     virtual Method* getMethod(const std::string& name) = 0;
-    virtual std::shared_ptr<Type> getType(const ast::Type& name) = 0;
-    virtual std::shared_ptr<Type> getReturnableType(void) = 0;
+    virtual std::optional<TypeId> getType(const ast::Type& name) = 0;
+    virtual std::optional<TypeId> getReturnableType(void) = 0;
     virtual Method* resolveMethod(const std::string& name,
-        const std::vector<std::shared_ptr<Type>> argumentTypes);
+        const std::vector<TypeId> argumentTypes);
 
     virtual std::string toString(void) = 0;
+
+    inline const Semantic& getSemantic(void) const { return semantic; }
 };
 
 
@@ -65,12 +78,18 @@ public:
     SymbolTable<Method> functions;
     OwningList<Cast> casts;
 public:
-    virtual Variable* getVariable(const std::string& name);
-    virtual Method* getMethod(const std::string& name);
-    virtual std::shared_ptr<Type> getType(const ast::Type& name);
-    virtual std::shared_ptr<Type> getReturnableType(void);
+    inline GlobalScope(const Semantic& semantic) :
+        Scope{ semantic }
+    {
+    }
+
+
+    virtual Variable* getVariable(const std::string& name) override;
+    virtual Method* getMethod(const std::string& name) override;
+    virtual std::optional<TypeId> getType(const ast::Type& name) override;
+    virtual std::optional<TypeId> getReturnableType(void) override;
 
-    virtual std::string toString(void);
+    virtual std::string toString(void) override;
 };
 
 
@@ -80,9 +99,14 @@ class qlow::sem::NativeScope : public GlobalScope
 public:
     SymbolTable<std::shared_ptr<NativeType>> types;
 public:
-    virtual std::shared_ptr<Type> getType(const ast::Type& name);
+    inline NativeScope(const Semantic& semantic) :
+        GlobalScope{ semantic }
+    {
+    }
 
-    virtual std::string toString(void);
+    virtual std::optional<TypeId> getType(const ast::Type& name);
+
+    virtual std::string toString(void) override;
     
     static NativeScope& getInstance(void);
 };
@@ -95,14 +119,17 @@ class qlow::sem::ClassScope : public Scope
     Class* classRef;
 public:
     inline ClassScope(Scope& parentScope, Class* classRef) :
-        parentScope{ parentScope }, classRef{ classRef }
+        Scope{ parentScope.getSemantic() },
+        parentScope{ parentScope },
+        classRef{ classRef }
     {
     }
-    virtual Variable* getVariable(const std::string& name);
-    virtual Method* getMethod(const std::string& name);
-    virtual std::shared_ptr<Type> getType(const ast::Type& name);
-    virtual std::shared_ptr<Type> getReturnableType(void);
-    virtual std::string toString(void);
+
+    virtual Variable* getVariable(const std::string& name) override;
+    virtual Method* getMethod(const std::string& name) override;
+    virtual std::optional<TypeId> getType(const ast::Type& name) override;
+    virtual std::optional<TypeId> getReturnableType(void) override;
+    virtual std::string toString(void) override;
 };
 
 
@@ -110,7 +137,7 @@ class qlow::sem::LocalScope : public Scope
 {
     Scope& parentScope;
     SymbolTable<Variable> localVariables;
-    std::shared_ptr<Type> returnType;
+    std::optional<TypeId> returnType;
     Method* enclosingMethod;
 public:
     LocalScope(Scope& parentScope, Method* enclosingMethod);
@@ -119,11 +146,11 @@ public:
     void putVariable(const std::string& name, std::unique_ptr<Variable> v);
     SymbolTable<Variable>& getLocals(void);
 
-    virtual Variable* getVariable(const std::string& name);
-    virtual Method* getMethod(const std::string& name);
-    virtual std::shared_ptr<Type> getType(const ast::Type& name);
-    virtual std::shared_ptr<Type> getReturnableType(void);
-    virtual std::string toString(void);
+    virtual Variable* getVariable(const std::string& name) override;
+    virtual Method* getMethod(const std::string& name) override;
+    virtual std::optional<TypeId> getType(const ast::Type& name) override;
+    virtual std::optional<TypeId> getReturnableType(void) override;
+    virtual std::string toString(void) override;
 };
 
 
@@ -132,17 +159,18 @@ class qlow::sem::TypeScope : public Scope
 protected:
     Type& type;
 public:
-    inline TypeScope(Type& type) :
+    inline TypeScope(const Semantic& semantic, Type& type) :
+        Scope{ semantic },
         type{ type }
     {
     }
     
     
-    virtual Variable* getVariable(const std::string& name);
-    virtual Method* getMethod(const std::string& name);
-    virtual std::shared_ptr<Type> getType(const ast::Type& name);
-    virtual std::shared_ptr<Type> getReturnableType(void);
-    virtual std::string toString(void);
+    virtual Variable* getVariable(const std::string& name) override;
+    virtual Method* getMethod(const std::string& name) override;
+    virtual std::optional<TypeId> getType(const ast::Type& name) override;
+    virtual std::optional<TypeId> getReturnableType(void) override;
+    virtual std::string toString(void) override;
 };
 
 
@@ -150,14 +178,14 @@ class qlow::sem::NativeTypeScope : public TypeScope
 {
     NativeType& nativeType;
 public:
-    inline NativeTypeScope(NativeType& type) :
-        TypeScope{ (Type&) type },
+    inline NativeTypeScope(const Semantic& semantic, NativeType& type) :
+        TypeScope{ semantic, (Type&) type },
         nativeType{ type }
     {
     }
     
     
-    virtual Method* getMethod(const std::string& name);
+    virtual Method* getMethod(const std::string& name) override;
     std::shared_ptr<Type> implementInlineOperation(const std::string&, llvm::Value* a);
 };
 

+ 0 - 99
src/main.cpp

@@ -1,108 +1,9 @@
-#include <iostream>
-
-#include <unistd.h>
-
-#include "Ast.h"
-#include "Semantic.h"
-#include "Builtin.h"
-#include "CodeGeneration.h"
-
 #include "Driver.h"
 
-
-extern std::unique_ptr<std::vector<std::unique_ptr<qlow::ast::Class>>> parsedClasses;
-extern FILE* qlow_parser_in;
-extern int qlow_parser_parse(void);
-
-
 int main(int argc, char** argv)
 {
-    /*int c;
-    while ((c = getopt(argc, argv, "c:")) != -1) {
-        switch (c) {
-            case 'c':
-                printf("c: %s", optarg);
-            break;
-            default:
-                printf("ay: %c\n", c);
-        }
-    }*/
-    
     qlow::Driver driver(argc, argv);
     return driver.run();
-
-    return 0;
-    /*
-    {
-    const char* filename = argv[optind];
-    
-    try {
-        ::qlow_parser_in = stdin;
-        
-        ::qlow_parser_in = fopen(filename, "r");
-        if (!::qlow_parser_in)
-            throw (std::string("File not found: ") + filename).c_str();
-        
-        ::qlow_parser_parse();
-        std::cout << parsedClasses->size() << std::endl;
-
-        std::cout << "parsing completed!" << std::endl;
-
-        std::unique_ptr<qlow::sem::GlobalScope> semClasses =
-            qlow::sem::createFromAst(*parsedClasses.get());
-
-        for (auto& [a, b] : semClasses->classes) {
-            std::cout << a << ": " << b->toString() << std::endl;
-        }
-
-        auto main = semClasses->classes.find("Main");
-        qlow::sem::Class* mainClass = nullptr;
-        if (main == semClasses->classes.end()) {
-            throw "No Main class found!";
-        }
-        else {
-            mainClass = main->second.get();
-        }
-        auto mainmain = mainClass->methods.find("main");
-        qlow::sem::Method* mainMethod = nullptr;
-        if (mainmain == mainClass->methods.end()) {
-            //throw "No main method found inside Main class!";
-        }
-        else {
-            mainMethod = mainmain->second.get();
-        }
-        
-        std::cout << "starting code generation!" << std::endl;
-
-        auto mod = qlow::gen::generateModule(semClasses->classes);
-        qlow::gen::generateObjectFile("obj.o", std::move(mod));
-        
-        std::cout << "object exported!" << std::endl;
-    }
-    catch (qlow::sem::SemanticException& se)
-    {
-        std::cerr << se.getMessage() << std::endl;
-    }
-    catch (const std::string& err)
-    {
-        std::cerr << err << std::endl;
-    }
-    catch (const char* err)
-    {
-        std::cerr << err << std::endl;
-    }
-    catch (...)
-    {
-        std::cerr << "an unknown error occurred" << std::endl;
-    }
-    
-    if (::qlow_parser_in != stdin)
-        fclose(::qlow_parser_in);
-    }
-
-    for (auto&& c : *parsedClasses) {
-        delete c.release();
-    }*/
 }
 
 

+ 2 - 2
src/makefile

@@ -5,8 +5,8 @@ CXX := clang++
 
 LLVMCONFIG := llvm-config-5.0
 
-INCLUDEDIRS := -I$(shell $(LLVMCONFIG) --includedir):. -I.. -Isem/
-CXXFLAGS := -std=c++17 $(INCLUDEDIRS) -w # -Wall -Wextra
+INCLUDEDIRS := -I$(shell $(LLVMCONFIG) --includedir) -I. -I.. -Isem/ -Iast/
+CXXFLAGS := -std=c++17 $(INCLUDEDIRS) -w $(FLAGS) # -Wall -Wextra
 
 ifdef STATIC
 LDFLAGS := $(shell $(LLVMCONFIG) --link-static --ldflags --system-libs --libs all) -static -dead-strip -s

+ 1 - 1
src/sem/Context.h

@@ -8,7 +8,7 @@ namespace qlow::sem
 {
     class Context;
     
-    using TypeId = size_t;
+    using TypeId = size_tg
 }
 
 

+ 3 - 4
src/sem/Semantic.cpp

@@ -16,8 +16,7 @@ namespace qlow
 namespace sem
 {
 
-std::unique_ptr<GlobalScope>
-    createFromAst(const std::vector<std::unique_ptr<qlow::ast::AstObject>>& objects)
+std::unique_ptr<Semantic> createFromAst(Ast& ast)
 {
     
     Logger& logger = Logger::getInstance();
@@ -28,7 +27,7 @@ std::unique_ptr<GlobalScope>
 
     // create classes
     std::unique_ptr<sem::GlobalScope> globalScope = std::make_unique<sem::GlobalScope>();
-    for (auto& astObject : objects) {
+    for (auto& astObject : ast.getObjects()) {
         if (auto* cls = dynamic_cast<ast::Class*>(astObject.get()); cls) {
             globalScope->classes[cls->name] = std::make_unique<sem::Class>(cls, *globalScope);
         }
@@ -106,7 +105,7 @@ std::unique_ptr<GlobalScope>
     printf("created all method bodies\n");
 #endif
     
-    return globalScope;
+    return std::make_unique<Semantic>(globalScope);
 }
 
 }

+ 31 - 17
src/sem/Semantic.h

@@ -18,8 +18,10 @@ namespace qlow
 {
     namespace sem
     {
-        std::unique_ptr<GlobalScope>
-            createFromAst(const std::vector<std::unique_ptr<qlow::ast::AstObject>>& objects);
+
+        class Semantic;
+
+        std::unique_ptr<Semantic> createFromAst(ast::Ast& ast);
 
         struct Class;
 
@@ -68,6 +70,18 @@ namespace qlow
 }
 
 
+class qlow::sem::Semantic
+{
+    std::unique_ptr<GlobalScope> globalScope;
+
+    std::vector<std::unique_ptr<Type>> types;
+public:
+    const SymbolTable<Class> getClasses(void) const;
+
+    TypeId getOrInsert(Class* cl);
+};
+
+
 struct qlow::sem::Class : public SemanticObject
 {
     qlow::ast::Class* astNode;
@@ -101,7 +115,7 @@ struct qlow::sem::Class : public SemanticObject
 
 struct qlow::sem::Variable : public SemanticObject
 {
-    std::shared_ptr<Type> type;
+    TypeId type;
     std::string name;
     bool isParameter;
 
@@ -110,13 +124,13 @@ struct qlow::sem::Variable : public SemanticObject
     llvm::Value* allocaInst;
     
     Variable(void) = default;
-    inline Variable(std::shared_ptr<Type> type, const std::string& name) :
-        type{ std::move(type) },
+    inline Variable(TypeId type, const std::string& name) :
+        type{ type },
         name{ name },
         allocaInst { nullptr }
     {
     }
-        
+
     virtual std::string toString(void) const override;
 };
 
@@ -131,7 +145,7 @@ struct qlow::sem::Field : public Variable
 struct qlow::sem::Method : public SemanticObject
 {
     Class* containingType;
-    std::shared_ptr<Type> returnType;
+    std::optional<TypeId> returnType;
     std::vector<Variable*> arguments;
     std::string name;
     ast::MethodDefinition* astNode;
@@ -142,7 +156,7 @@ struct qlow::sem::Method : public SemanticObject
 
     llvm::Function* llvmNode;
 
-    inline Method(Scope& parentScope, std::shared_ptr<Type> returnType) :
+    inline Method(Scope& parentScope, std::optional<TypeId> returnType) :
         containingType{ nullptr },
         returnType{ std::move(returnType) },
         scope{ parentScope, this },
@@ -171,7 +185,7 @@ struct qlow::sem::ThisExpression : public Variable
 {
     Method* method;
     inline ThisExpression(Method* method) :
-        Variable{ std::make_shared<PointerType>(std::make_shared<ClassType>(method->containingType)), "this" },
+        Variable{ ClassType{ method->containingType }, "this" },
         method{ method }
     {
     }
@@ -261,7 +275,7 @@ struct qlow::sem::Expression :
 {
     std::shared_ptr<sem::Type> type;
     
-    inline Expression(std::shared_ptr<Type> type) :
+    inline Expression(std::optional<TypeId> type) :
         type{ std::move(type) }
     {
     }
@@ -277,7 +291,7 @@ struct qlow::sem::Operation : public Expression
 {
     std::string opString;
     
-    inline Operation(std::shared_ptr<Type> type) :
+    inline Operation(std::optional<TypeId> type) :
         Expression{ std::move(type) }
     {
     }
@@ -325,7 +339,7 @@ struct qlow::sem::BinaryOperation : public Operation
     /// method that is called to execute the operator
     sem::Method* operationMethod;
     
-    inline BinaryOperation(std::shared_ptr<Type> type, ast::BinaryOperation* astNode) :
+    inline BinaryOperation(std::optional<TypeId> type, ast::BinaryOperation* astNode) :
         Operation{ std::move(type) },
         astNode{ astNode }
     {
@@ -340,12 +354,12 @@ struct qlow::sem::BinaryOperation : public Operation
 struct qlow::sem::CastExpression : public Expression
 {
     std::unique_ptr<Expression> expression;
-    std::shared_ptr<Type> targetType;
+    std::optional<TypeId> targetType;
     
     ast::CastExpression* astNode;
     
     inline CastExpression(std::unique_ptr<Expression> expression,
-                          std::shared_ptr<Type> type,
+                          std::optional<TypeId> type,
                           ast::CastExpression* astNode) :
         Expression{ type },
         expression{ std::move(expression) },
@@ -362,10 +376,10 @@ struct qlow::sem::CastExpression : public Expression
 
 struct qlow::sem::NewArrayExpression : public Expression
 {
-    std::shared_ptr<Type> arrayType;
+    std::optional<TypeId> arrayType;
     std::unique_ptr<Expression> length;
     
-    inline NewArrayExpression(std::shared_ptr<Type> arrayType) :
+    inline NewArrayExpression(std::optional<TypeId> arrayType) :
         Expression{ std::make_shared<ArrayType>(arrayType) },
         arrayType{ std::move(arrayType) }
     {
@@ -381,7 +395,7 @@ struct qlow::sem::UnaryOperation : public Operation
     qlow::ast::UnaryOperation::Side side;
     std::unique_ptr<Expression> arg;
     
-    inline UnaryOperation(std::shared_ptr<Type> type) :
+    inline UnaryOperation(std::optional<TypeId> type) :
         Operation{ std::move(type) }
     {
     }

+ 39 - 25
src/sem/Type.h

@@ -26,6 +26,7 @@ namespace qlow
     namespace sem
     {
         struct SemanticObject;
+        class Semantic;
         
         class Type;
         
@@ -50,7 +51,15 @@ struct qlow::sem::SemanticObject
 
 class qlow::sem::Type : public SemanticObject
 {
+protected:
+    const Semantic& semantic;
 public:
+
+    inline Type(const Semantic& semantic) :
+        semantic{ semantic }
+    {
+    }
+
     virtual ~Type(void);
 
     /// \returns false by default
@@ -80,24 +89,25 @@ public:
 
 class qlow::sem::PointerType : public Type
 {
-    std::shared_ptr<Type> derefType;
+    //std::shared_ptr<Type> derefType;
+    TypeId derefType;
     sem::TypeScope scope;
 public:
-    inline PointerType(std::shared_ptr<Type> derefType) :
-        derefType{ derefType },
-        scope{ *this }
+    inline PointerType(const Semantic& semantic) :
+        Type{ semantic },
+        scope{ semantic, *this }
     {
     }
-    
-    const std::shared_ptr<Type>& getDerefType(void) const { return derefType; }
-    
+
+    TypeId getDerefType(void) const { return derefType; }
+
     inline bool isPointerType(void) const override { return true; }
-    
+
     virtual std::string asString(void) const override;
     virtual Scope& getScope(void) override;
-    
+
     virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
-    
+
     virtual bool equals(const Type& other) const override;
 };
 
@@ -107,32 +117,34 @@ class qlow::sem::ClassType : public Type
     sem::Class* classType;
     sem::TypeScope scope;
 public:
-    inline ClassType(sem::Class* classType) :
+    inline ClassType(const Semantic& semantic, sem::Class* classType) :
+        Type{ semantic },
         classType{ classType },
-        scope{ *this }
+        scope{ semantic, *this }
     {
     }
-    
+
     inline bool isClassType(void) const override { return true; }
-    
+
     std::string asString(void) const;
     Scope& getScope(void);
-    
+
     virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
     inline sem::Class* getClassType(void) { return classType; }
-    virtual bool equals(const Type& other) const;
+    virtual bool equals(const Type& other) const override;
 };
 
 
 class qlow::sem::ArrayType : public Type
 {
-    std::shared_ptr<sem::Type> arrayType;
+    TypeId arrayType;
     TypeScope scope;
 public:
     
-    inline ArrayType(std::shared_ptr<sem::Type> arrayType) :
-        arrayType{ std::move(arrayType) },
-        scope{ *this }
+    inline ArrayType(const Semantic& semantic, TypeId arrayType) :
+        Type{ semantic },
+        arrayType{ arrayType },
+        scope{semantic, *this }
     {
     }
     
@@ -142,8 +154,8 @@ public:
     Scope& getScope(void);
     
     virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
-    inline std::shared_ptr<sem::Type> getArrayType(void) { return arrayType; }
-    virtual bool equals(const Type& other) const;
+    inline TypeId getArrayType(void) { return arrayType; }
+    virtual bool equals(const Type& other) const override;
 };
 
 
@@ -166,9 +178,10 @@ public:
     
     SymbolTable<NativeMethod> nativeMethods;
     
-    inline NativeType(Type type) :
+    inline NativeType(const Semantic& semantic, Type type) :
+        sem::Type{ semantic },
         type{ type },
-        scope{ *this }
+        scope{ semantic, *this }
     {
     }
     
@@ -180,7 +193,7 @@ public:
     bool isIntegerType(void) const;
     
     llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
-    virtual bool equals(const sem::Type& other) const;
+    virtual bool equals(const sem::Type& other) const override;
     
     /// cast an llvm::Value from another native type to this one
     llvm::Value* generateImplicitCast(llvm::Value* value);
@@ -188,3 +201,4 @@ public:
 
 
 #endif // QLOW_SEM_TYPE_H
+