Explorar el Código

added structs

Nicolas Winkler hace 6 años
padre
commit
5c19b3506d

+ 40 - 8
src/Builtin.cpp

@@ -128,10 +128,20 @@ void qlow::sem::fillNativeScope(NativeScope& scope)
 {
     Context& context = scope.getContext();
 
-    Type* integer = context.getNativeType(NativeType::NType::INTEGER);
-    integer->setTypeScope(
-        std::make_unique<NativeTypeScope>(generateNativeTypeScope(context, NativeType::NType::INTEGER))
-    );
+    static const std::vector<NativeType::NType> integerTypes {
+        NativeType::NType::INTEGER,
+        NativeType::NType::C_CHAR,
+        NativeType::NType::C_SHORT,
+        NativeType::NType::C_INT,
+        NativeType::NType::C_LONG,
+    };
+
+    for (auto integerType : integerTypes) {
+        Type* integer = context.getNativeType(integerType);
+        integer->setTypeScope(
+            std::make_unique<NativeTypeScope>(generateNativeTypeScope(context, integerType))
+        );
+    }
 }
 
 
@@ -143,7 +153,7 @@ sem::NativeTypeScope qlow::sem::generateNativeTypeScope(Context& context, Native
     scope.nativeMethods.insert(
         { "+",
             std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
-                context.getNativeType(NativeType::NType::INTEGER),
+                context.getNativeType(native),
                 context.getNativeType(native),
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
                     return builder.CreateAdd(a, b);
@@ -154,7 +164,7 @@ sem::NativeTypeScope qlow::sem::generateNativeTypeScope(Context& context, Native
     scope.nativeMethods.insert(
         { "-",
             std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
-                context.getNativeType(NativeType::NType::INTEGER),
+                context.getNativeType(native),
                 context.getNativeType(native),
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
                     return builder.CreateSub(a, b);
@@ -165,7 +175,7 @@ sem::NativeTypeScope qlow::sem::generateNativeTypeScope(Context& context, Native
     scope.nativeMethods.insert(
         { "*",
             std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
-                context.getNativeType(NativeType::NType::INTEGER),
+                context.getNativeType(native),
                 context.getNativeType(native),
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
                     return builder.CreateMul(a, b);
@@ -176,7 +186,7 @@ sem::NativeTypeScope qlow::sem::generateNativeTypeScope(Context& context, Native
     scope.nativeMethods.insert(
         { "/",
             std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
-                context.getNativeType(NativeType::NType::INTEGER),
+                context.getNativeType(native),
                 context.getNativeType(native),
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
                     return builder.CreateSDiv(a, b);
@@ -208,6 +218,28 @@ sem::NativeTypeScope qlow::sem::generateNativeTypeScope(Context& context, Native
             )
         }
     );
+    scope.nativeMethods.insert(
+        { "<",
+            std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
+                context.getNativeType(NativeType::NType::BOOLEAN),
+                context.getNativeType(native),
+                [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                    return builder.CreateICmpSLT(a, b);
+                }
+            )
+        }
+    );
+    scope.nativeMethods.insert(
+        { ">",
+            std::make_unique<BinaryNativeMethod>(context.getNativeScope(),
+                context.getNativeType(NativeType::NType::BOOLEAN),
+                context.getNativeType(native),
+                [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                    return builder.CreateICmpSGT(a, b);
+                }
+            )
+        }
+    );
 
     return scope;
 }

+ 9 - 7
src/CodegenVisitor.cpp

@@ -17,8 +17,8 @@ using namespace qlow;
 llvm::Value* ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
 {
     assert(lve.var->allocaInst != nullptr);
-    // TODO improve handling of arrays
-    if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst) && !lve.type->isArrayType()) {
+    // TODO improve handling of arrays and structs
+    if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst) && !lve.type->isArrayType() && !lve.type->isStructType()) {
         llvm::Type* returnType = lve.type->getLlvmType(builder.getContext());
         llvm::Value* val = builder.CreateLoad(returnType, lve.var->allocaInst);
         return val;
@@ -236,8 +236,8 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access,
     if (type->isPointerTy()) {
         type = type->getPointerElementType();
     }
-    
-    llvm::Value* target = access.target->accept(fg.lvalueVisitor, fg);
+
+    llvm::Value* target = access.target->accept(fg.expressionVisitor, builder);
 
     int structIndex = access.accessed->llvmStructIndex;
     llvm::ArrayRef<Value*> indexList = {
@@ -245,7 +245,8 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access,
         llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
     };
 
-    Value* ptr = builder.CreateGEP(type, target, indexList);
+    //Value* ptr = builder.CreateGEP(type, target, indexList);
+    Value* ptr = fg.builder.CreateStructGEP(type, target, structIndex);
     return builder.CreateLoad(ptr);
     
     
@@ -377,7 +378,8 @@ llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, qlow::gen:
         llvm::ConstantInt::get(fg.builder.getContext(), llvm::APInt(32, structIndex, false)),
         llvm::ConstantInt::get(fg.builder.getContext(), llvm::APInt(32, 0, false))
     };
-    Value* ptr = fg.builder.CreateGEP(type, target, indexList);
+    //Value* ptr = fg.builder.CreateGEP(type, target, indexList);
+    Value* ptr = fg.builder.CreateStructGEP(type, target, structIndex);
     return ptr;
 }
 
@@ -501,7 +503,7 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
     auto val = assignment.value->accept(fg.expressionVisitor, fg.builder);
     auto target = assignment.target->accept(fg.lvalueVisitor, fg);
     
-    if (val->getType()->isPointerTy() && val->getType()->getPointerElementType()->isStructTy()) {
+    if (!assignment.value->type->isNativeType() && !assignment.value->type->isReferenceType()) {
         const llvm::DataLayout& layout = fg.builder.GetInsertBlock()->getModule()->getDataLayout();
 #if LLVM_VERSION_MAJOR >= 7
         return fg.builder.CreateMemCpy(target, 1, val, 1, layout.getTypeAllocSize(val->getType()->getPointerElementType()), false);

+ 1 - 1
src/Driver.cpp

@@ -254,7 +254,7 @@ bool Driver::semanticStage(void)
 {
     Printer& printer = Printer::getInstance();
     bool errorOccurred = false;
-
+    #error YOU SHALL BE ASSIMILATED INTO SPARKLING UNIVERSE DUST
     try {
         std::tie(this->context, this->semClasses) = qlow::sem::createFromAst(*this->ast);
     }

+ 24 - 20
src/ast/AstVisitor.cpp

@@ -184,10 +184,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& as
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope)
 {
+    // TODO rewrite this mess
+
     std::unique_ptr<sem::Expression> target = nullptr;
     if (ast.target) {
-        target = unique_dynamic_cast<sem::Expression>(
-            ast.target->accept(*this, scope));
+        auto expr = ast.target->accept(*this, scope);
+        target = unique_dynamic_cast<sem::Expression>(std::move(expr));
     }
 
     sem::Method* method;
@@ -217,18 +219,10 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
                 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 != argTypeShouldHave)
-                        throw SemanticError(SemanticError::TYPE_MISMATCH,
-                            "argument passed to function has wrong type",
-                            // TODO rewrite types
-                            //expr->type->asString() + "' instead of '" +
-                            //argTypeShouldHave->asString() + "'",
-                            arg->pos
-                        );
-                    fce->arguments.push_back(
-                        unique_dynamic_cast<sem::Expression>(std::move(argument)));
+                if (dynamic_cast<sem::Expression*>(argument.get())) {
+                    auto expr = unique_dynamic_cast<sem::Expression>(std::move(argument));
+                    auto castedParameter = createImplicitCast(std::move(expr), argTypeShouldHave, scope);
+                    fce->arguments.push_back(std::move(castedParameter));
                 }
                 else {
                     throw "internal error: non-expression passed as function parameter";
@@ -260,11 +254,18 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
                 throw SemanticError(SemanticError::UNKNOWN_TYPE, "no this found", ast.pos);
             thisExpr = std::make_unique<sem::LocalVariableExpression>(thisVar, CodePosition::none());
         }
+        if (ast.arguments.size() != method->arguments.size())
+                throw SemanticError(SemanticError::WRONG_NUMBER_OF_ARGUMENTS, ast.name, ast.pos);
         auto fce = std::make_unique<sem::MethodCallExpression>(std::move(thisExpr), method, ast.pos);
-        for (auto& arg : ast.arguments) {
+        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 (dynamic_cast<sem::Expression*>(argument.get())) {
-                fce->arguments.push_back(unique_dynamic_cast<sem::Expression>(std::move(argument)));
+                auto expr = unique_dynamic_cast<sem::Expression>(std::move(argument));
+                auto castedParameter = createImplicitCast(std::move(expr), argTypeShouldHave, scope);
+                fce->arguments.push_back(std::move(castedParameter));
             }
             else {
                 throw "internal error: non-expression passed as function parameter";
@@ -286,12 +287,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::AssignmentStatement& ast, sem::Scope& scope)
 {
     auto as = std::make_unique<sem::AssignmentStatement>(scope.getContext());
-    
+
 //    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->operator==(*as->value->type)) {
         return as;
     }
@@ -464,11 +465,14 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::CastExpression
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::createImplicitCast(
+std::unique_ptr<sem::Expression> StructureVisitor::createImplicitCast(
         std::unique_ptr<sem::Expression> expr, sem::Type* targetType, sem::Scope& scope)
 {
+    Printer::getInstance() << "casting " << expr->type->asString() << " to " << targetType->asString() << std::endl;
+    if (expr->type->equals(*targetType))
+        return expr;
     auto* exprType = expr->type;
-    if (/*exprType->isImplicitelyCastableTo(targetType)*/true) {
+    if (false /*exprType->isImplicitelyCastableTo(targetType)*/) {
         return std::make_unique<sem::CastExpression>(
             std::move(expr), targetType, nullptr, true, expr->pos);
     }

+ 1 - 1
src/ast/AstVisitor.h

@@ -85,7 +85,7 @@ public:
     ReturnType visit(ast::NewArrayExpression& ast, sem::Scope& scope) override;
     ReturnType visit(ast::CastExpression& ast, sem::Scope& scope) override;
 
-    ReturnType createImplicitCast(std::unique_ptr<sem::Expression>, sem::Type* targetType, sem::Scope& scope);
+    std::unique_ptr<sem::Expression> createImplicitCast(std::unique_ptr<sem::Expression>, sem::Type* targetType, sem::Scope& scope);
 };
 
 

+ 1 - 1
src/ast/syntax.y

@@ -107,7 +107,7 @@ while (0)
 
 %initial-action
 {
-    @$.filename = parser.getFilename();
+        @$.filename = parser.getFilename();
     qlow_parser_set_extra(parser.getFilename(), scanner);
 };
 

+ 2 - 2
src/sem/Context.cpp

@@ -35,7 +35,7 @@ qlow::sem::NativeScope& Context::getNativeScope(void)
 
 sem::Type* Context::getNativeType(NativeType::NType nativeType)
 {
-    auto t = std::unique_ptr<NativeType>(new NativeType(nativeType));
+    auto t = std::unique_ptr<NativeType>(new NativeType(*this, nativeType));
 
     const auto& find = typeMap.find(t.get());
     if (find != typeMap.end()) {
@@ -51,7 +51,7 @@ sem::Type* Context::getNativeType(NativeType::NType nativeType)
 
 sem::Type* Context::getClassType(Class* classType)
 {
-    auto t = std::unique_ptr<ClassType>(new ClassType(classType));
+    auto t = std::unique_ptr<ClassType>(new ClassType(*this, classType));
 
     const auto& find = typeMap.find(t.get());
     if (find != typeMap.end()) {

+ 35 - 5
src/sem/Type.cpp

@@ -23,7 +23,13 @@ std::string qlow::sem::SemanticObject::toString(void) const
     return "SemanticObject [" + util::toString(this) + "]";
 }
 
-Type::Type(void) = default;
+Type::Type(Context& context) :
+    typeScope{ std::make_unique<TypeScope>(context, this) },
+    context{ context }
+{
+}
+
+
 Type::~Type(void) = default;
 
 
@@ -46,6 +52,12 @@ Type* Type::getArrayOf(void) const
 }
 
 
+bool Type::isReferenceType(void) const
+{
+    return false;
+}
+
+
 void Type::setTypeScope(std::unique_ptr<TypeScope> scope)
 {
     this->typeScope = std::move(scope);
@@ -70,6 +82,12 @@ bool Type::isClassType(void) const
 }
 
 
+bool Type::isStructType(void) const
+{
+    return false;
+}
+
+
 bool Type::isNativeType(void) const
 {
     return false;
@@ -195,15 +213,27 @@ bool ClassType::equals(const Type& other) const
 }
 
 
-qlow::sem::Class* ClassType::getClass(void) const
+bool ClassType::isClassType(void) const
 {
-    return type;
+    return true;
 }
 
 
-bool ClassType::isClassType(void) const
+bool ClassType::isStructType(void) const
 {
-    return true;
+    return !getClass()->isReferenceType;
+}
+
+
+bool ClassType::isReferenceType(void) const
+{
+    return getClass()->isReferenceType;
+}
+
+
+qlow::sem::Class* ClassType::getClass(void) const
+{
+    return type;
 }
 
 

+ 14 - 5
src/sem/Type.h

@@ -44,16 +44,15 @@ struct qlow::sem::SemanticObject
 };
 
 
-
 class qlow::sem::Type
 {
     friend class Context;
 protected:
     std::unique_ptr<TypeScope> typeScope;
     llvm::Type* llvmType;
+    Context& context;
 
-    Type(void);
-
+    Type(Context& context);
 public:
 
     virtual ~Type(void);
@@ -87,6 +86,8 @@ public:
      *         <code>nullptr</code> if this type is not an array type.
      */
     virtual Type* getArrayOf(void) const;
+
+    virtual bool isReferenceType(void) const;
     
     /**
      * @brief returns the type scope of this type
@@ -104,10 +105,13 @@ public:
     virtual void createLlvmTypeDecl(llvm::LLVMContext&) = 0;
 
     virtual bool isClassType(void) const;
+    virtual bool isStructType(void) const;
     virtual bool isNativeType(void) const;
     virtual bool isArrayType(void) const;
 
     virtual bool isVoid(void) const;
+
+    inline Context& getContext(void) const { return context; }
 };
 
 
@@ -129,7 +133,8 @@ public:
 protected:
 
     NType type;
-    inline NativeType(NType type) :
+    inline NativeType(Context& context, NType type) :
+        Type{ context },
         type{ type }
     {
     }
@@ -153,13 +158,16 @@ class qlow::sem::ClassType : public Type
     friend class Context;
 protected:
     Class* type;
-    inline ClassType(Class* type) :
+    inline ClassType(Context& context, Class* type) :
+        Type{ context },
         type{ type }
     {
     }
 public:
     virtual bool equals(const Type& other) const override;
     virtual bool isClassType(void) const override;
+    virtual bool isStructType(void) const override;
+    virtual bool isReferenceType(void) const override;
     virtual Class* getClass(void) const override;
 
     virtual std::string asString(void) const override;
@@ -175,6 +183,7 @@ class qlow::sem::ArrayType : public Type
 protected:
     Type* elementType;
     inline ArrayType(Type* elementType) :
+        Type{ elementType->getContext() },
         elementType{ elementType }
     {
     }

+ 8 - 19
src/test.qlw

@@ -1,27 +1,16 @@
 import some
 
-
-class Aalala
-
-end
-
-/*
-bignumbers do
-    a: Int128
-    b: Int128
-    c: Int64
-
-    b := a + c as Int128
-    //c := b as Int64
+struct Pair
+    a: Integer
+    b: Integer
 end
-*/
 
 main: Integer do
-    count: CInt
-    count := 0
-    while count != 20 do
-        printint(fast_fibonacci(count))
-        count := count + 1
+    count: Pair
+    count.a := 0
+    while count.a != 20 do
+        printint(fast_fibonacci(count.a))
+        count.a := count.a + 1
     end
     return 0
     //do_shit

+ 7 - 2
tests/runTests.py

@@ -19,16 +19,21 @@ def test_file(path):
     test = [qlow_executable, path, "-o", path + ".o"]
     print("running test " + " ".join(test))
     output = subprocess.run(test, stdout=subprocess.PIPE)
-    with open(path + ".c.did", "w") as out:
+    with open(path + ".c.out", "w") as out:
         out.write(output.stdout.decode("utf-8"))
     
-    with open(path + ".c.did", "r") as did, open(path + ".c.should", "r") as should:
+    with open(path + ".c.out", "r") as did, open(path + ".c.out.ref", "r") as should:
         if did.readlines() == should.readlines():
             global succeeded
             succeeded += 1
         else:
             global failed
             failed += 1
+    
+    exefile = path + ".o"
+    if os.path.isfile(exefile):
+        runOut = subprocess.run(exefile, stdout=subprocess.PIPE)
+
 
 
 

+ 0 - 0
tests/syntax/class.qlw.c.should