Parcourir la source

Merge branch 'types' of http://192.168.1.47/nicolas/qlow into types

Nicolas Winkler il y a 6 ans
Parent
commit
44615c103f
13 fichiers modifiés avec 151 ajouts et 71 suppressions
  1. 4 2
      src/CMakeLists.txt
  2. 3 2
      src/Driver.h
  3. 7 0
      src/ErrorReporting.cpp
  4. 2 0
      src/ErrorReporting.h
  5. 21 15
      src/Scope.cpp
  6. 8 7
      src/Scope.h
  7. 5 12
      src/ast/AstVisitor.cpp
  8. 2 0
      src/ast/lexer.l
  9. 9 9
      src/ast/syntax.y
  10. 11 7
      src/sem/Context.cpp
  11. 8 1
      src/sem/Context.h
  12. 46 10
      src/sem/Type.cpp
  13. 25 6
      src/sem/Type.h

+ 4 - 2
src/CMakeLists.txt

@@ -38,8 +38,10 @@ add_definitions( ${LLVM_DEFINITIONS} )
 
 
 if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG )
-    target_compile_options(${PROJECT_NAME} PRIVATE "-Wall -Wextra -Wconversion -Wsign-conversion")
-    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}  -g -DDEBUGGING -std=gnu++17")
+    target_compile_options(${PROJECT_NAME} PRIVATE 
+        -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
+    )
+    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -DDEBUGGING")
 endif()
 if ( MSVC )
     target_compile_options(${PROJECT_NAME} PRIVATE "/W4")

+ 3 - 2
src/Driver.h

@@ -16,8 +16,9 @@ namespace qlow
     class Driver;
     
     
-    namespace ast {
-        struct Ast;
+    namespace ast
+    {
+        class Ast;
         struct AstObject;
     }
 }

+ 7 - 0
src/ErrorReporting.cpp

@@ -203,3 +203,10 @@ std::string SemanticError::getMessage(void) const noexcept
 }
 
 
+SemanticError SemanticError::invalidReturnType(const std::string& should,
+    const std::string& is, const CodePosition& where)
+{
+    return SemanticError{ INVALID_RETURN_TYPE, "invalid return type: return type should be " +
+        should + ", but " + is + " is given.", where };
+}
+

+ 2 - 0
src/ErrorReporting.h

@@ -137,6 +137,8 @@ public:
 
     virtual void print(Printer& p = Printer::getInstance()) const noexcept override;
     virtual std::string getMessage(void) const noexcept;
+
+    static SemanticError invalidReturnType(const std::string& should, const std::string& is, const CodePosition& where);
 };
 
 

+ 21 - 15
src/Scope.cpp

@@ -64,7 +64,7 @@ sem::TypeId sem::GlobalScope::getType(const ast::Type* name)
     if (native) {
         return native;
     }
-    
+
     const auto* classType = dynamic_cast<const ast::ClassType*>(name);
    
     if (!classType)
@@ -108,7 +108,7 @@ sem::TypeId sem::NativeScope::getType(const ast::Type* name)
    
     if (!classType)
         return NO_TYPE;
-    
+
     
     auto t = types.find(classType->typeName);
     if (t != types.end())
@@ -269,12 +269,10 @@ std::string sem::LocalScope::toString(void)
 
 sem::Variable* sem::TypeScope::getVariable(const std::string& name)
 {
-    if (auto ty = context.getType(type)) {
-        if (ty.value().get().getKind() == Type::Kind::CLASS) {
-            auto& fields = ty.value().get().getClass()->fields;
-            if (fields.find(name) != fields.end())
-                return fields[name].get();
-        }
+    if (type.getKind() == Type::Kind::CLASS) {
+        auto& fields = type.getClass()->fields;
+        if (fields.find(name) != fields.end())
+            return fields[name].get();
     }
     return nullptr;
 }
@@ -283,13 +281,11 @@ sem::Variable* sem::TypeScope::getVariable(const std::string& name)
 
 sem::Method* sem::TypeScope::getMethod(const std::string& name)
 {
-    if (auto ty = context.getType(type)) {
-        if (ty.value().get().getKind() == Type::Kind::CLASS) {
-            auto classRef = ty.value().get().getClass();
-            auto& methods = classRef->methods;
-            if (methods.find(name) != methods.end())
-                return methods[name].get();
-        }
+    if (type.getKind() == Type::Kind::CLASS) {
+        auto classRef = type.getClass();
+        auto& methods = classRef->methods;
+        if (methods.find(name) != methods.end())
+            return methods[name].get();
     }
     return nullptr;
 }
@@ -314,6 +310,12 @@ std::string sem::TypeScope::toString(void)
 }
 
 
+bool sem::TypeScope::isNativeTypeScope(void) const
+{
+    return false;
+}
+
+
 sem::Method* sem::NativeTypeScope::getMethod(const std::string& name)
 {
     /*auto m = nativeType.nativeMethods.find(name);
@@ -324,5 +326,9 @@ sem::Method* sem::NativeTypeScope::getMethod(const std::string& name)
 }
 
 
+bool sem::NativeTypeScope::isNativeTypeScope(void) const
+{
+    return true;
+}
 
 

+ 8 - 7
src/Scope.h

@@ -151,9 +151,9 @@ public:
 class qlow::sem::TypeScope : public Scope
 {
 protected:
-    TypeId type;
+    Type& type;
 public:
-    inline TypeScope(Context& context, TypeId type) :
+    inline TypeScope(Context& context, Type& type) :
         Scope{ context },
         type{ type }
     {
@@ -164,21 +164,22 @@ public:
     virtual TypeId getType(const ast::Type* name);
     virtual TypeId getReturnableType(void);
     virtual std::string toString(void);
+
+    virtual bool isNativeTypeScope(void) const;
 };
 
 
 class qlow::sem::NativeTypeScope : public TypeScope
 {
-    TypeId nativeType;
 public:
-    inline NativeTypeScope(Context& context, TypeId type) :
-        TypeScope{ context, type },
-        nativeType{ type }
+    inline NativeTypeScope(Context& context, Type& type) :
+        TypeScope{ context, type }
     {
     }
     
-    
     virtual Method* getMethod(const std::string& name);
+    virtual bool isNativeTypeScope(void) const;
+
     TypeId implementInlineOperation(const std::string&, llvm::Value* a);
 };
 

+ 5 - 12
src/ast/AstVisitor.cpp

@@ -326,14 +326,9 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ReturnStatemen
     auto returnValue = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
     
     if (shouldReturn != returnValue->type) {
-        throw SemanticError(
-            SemanticError::INVALID_RETURN_TYPE,
-            //TODO rewrite
-            "wrong return value",
-            //"return value must be of type '" + shouldReturn->asString() + "' (not '" +
-            //returnValue->type->asString() + "')",
-            ast.expr->pos
-        );
+        auto should = scope.getContext().getTypeString(shouldReturn);
+        auto is = scope.getContext().getTypeString(returnValue->type);
+        throw SemanticError::invalidReturnType(should, is, ast.expr->pos);
     }
     
     auto as = std::make_unique<sem::ReturnStatement>(scope.getContext());
@@ -352,12 +347,10 @@ 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;
+    auto targetType = target->type;
     
     if (!target->isLValue()) {
-        // TODO rewrite
-        //throw NotLValue(targetType->asString(), ast.pos);
-        throw NotLValue("type", ast.pos);
+        throw NotLValue(scope.getContext().getTypeString(targetType), ast.pos);
     }
     
     return std::make_unique<sem::AddressExpression>(std::move(target));

+ 2 - 0
src/ast/lexer.l

@@ -41,7 +41,9 @@
 
 extern "C" int qlow_parser_wrap(yyscan_t s);
 
+#ifdef _WIN32
 #define YY_NO_UNISTD_H
+#endif
 
 // TODO rewrite
 #define YY_USER_ACTION                                \

+ 9 - 9
src/ast/syntax.y

@@ -222,19 +222,19 @@ topLevel:
     |
     topLevel classDefinition {
         $$ = $1;
-        $$->getObjects().push_back(std::move(std::unique_ptr<qlow::ast::Class>($2)));
+        $$->getObjects().emplace_back($2);
         $2 = nullptr;
     }
     |
     topLevel methodDefinition {
         $$ = $1;
-        $$->getObjects().push_back(std::move(std::unique_ptr<qlow::ast::MethodDefinition>($2)));
+        $$->getObjects().emplace_back($2);
         $2 = nullptr;
     }
     |
     topLevel externMethodDeclaration {
         $$ = $1;
-        $$->getObjects().push_back(std::move(std::unique_ptr<qlow::ast::MethodDefinition>($2)));
+        $$->getObjects().emplace_back($2);
         $2 = nullptr;
     }
     |
@@ -242,7 +242,7 @@ topLevel:
         $$ = $1;
         reportError(qlow::SyntaxError(@2));
         yyerrok;
-        $$->getObjects().push_back(std::move(std::unique_ptr<qlow::ast::MethodDefinition>($3)));
+        $$->getObjects().emplace_back($3);
         $3 = nullptr;
     }
     |
@@ -250,7 +250,7 @@ topLevel:
         reportError(qlow::SyntaxError(@2));
         yyerrok;
         $$ = $1;
-        $$->getObjects().push_back(std::move(std::unique_ptr<qlow::ast::Class>($3)));
+        $$->getObjects().emplace_back($3);
         $3 = nullptr;
     };
 
@@ -296,7 +296,7 @@ featureList:
     |
     featureList featureDeclaration {
         $$ = $1;
-        $$->push_back(std::move(std::unique_ptr<FeatureDeclaration>($2)));
+        $$->emplace_back($2);
         $2 = nullptr;
     }
     |
@@ -304,7 +304,7 @@ featureList:
         $$ = $1;
         yyerrok;
         reportError(qlow::SyntaxError(@2));
-        $$->push_back(std::move(std::unique_ptr<FeatureDeclaration>($3)));
+        $$->emplace_back($3);
         $3 = nullptr;
     };
 
@@ -356,7 +356,7 @@ methodDefinition:
     }
     |
     IDENTIFIER doEndBlock {
-        $$ = new MethodDefinition(nullptr, *$1, std::move(std::unique_ptr<DoEndBlock>($2)), @$);
+        $$ = new MethodDefinition(nullptr, *$1, std::unique_ptr<DoEndBlock>($2), @$);
         delete $1; $1 = nullptr;
     }
     |
@@ -370,7 +370,7 @@ methodDefinition:
     }
     |
     IDENTIFIER ROUND_LEFT argumentList ROUND_RIGHT doEndBlock {
-        $$ = new MethodDefinition(nullptr, *$1, std::move(*$3), std::move(std::unique_ptr<DoEndBlock>($5)), @$);
+        $$ = new MethodDefinition(nullptr, *$1, std::move(*$3), std::unique_ptr<DoEndBlock>($5), @$);
         delete $1; delete $3; $1 = nullptr; $3 = nullptr;
     };
 

+ 11 - 7
src/sem/Context.cpp

@@ -22,7 +22,8 @@ qlow::sem::TypeId Context::addType(Type&& type) {
         return typesMap[type];
     }
     else {
-        types.push_back(std::move(type));
+        Type gogo = std::move(type);
+        types.push_back(std::move(gogo));
         return types.size() - 1;
     }
 }
@@ -39,6 +40,15 @@ std::optional<std::reference_wrapper<qlow::sem::Type>> Context::getType(TypeId t
 }
 
 
+std::string Context::getTypeString(TypeId tid)
+{
+    if (auto type = getType(tid))
+        return type.value().get().asString();
+    else
+        return "";
+}
+
+
 qlow::sem::TypeId Context::getPointerTo(TypeId id)
 {
     return addType(Type::createPointerType(*this, id));
@@ -63,12 +73,6 @@ qlow::sem::TypeId Context::getNativeTypeId(Type::Native n)
 }
 
 
-std::unique_ptr<qlow::sem::TypeScope> Context::getTypeScope(TypeId id)
-{
-    return std::make_unique<TypeScope>(*this, id);
-}
-
-
 qlow::sem::NativeScope& Context::getNativeScope(void)
 {
     return *nativeScope;

+ 8 - 1
src/sem/Context.h

@@ -41,6 +41,14 @@ public:
     TypeId addType(Type&& type);
     std::optional<std::reference_wrapper<Type>> getType(TypeId tid);
 
+    /**
+     * @brief get a string denoting the type
+     * 
+     * @return the name of the type if the given id is valid,
+     *         an empty string otherwise.
+     */
+    std::string getTypeString(TypeId tid);
+
     TypeId getPointerTo(TypeId id);
     TypeId getArrayOf(TypeId id);
 
@@ -48,7 +56,6 @@ public:
     TypeId getVoidTypeId(void);
     TypeId getNativeTypeId(Type::Native n);
 
-    std::unique_ptr<TypeScope> getTypeScope(TypeId);
     NativeScope& getNativeScope(void);
 };
 

+ 46 - 10
src/sem/Type.cpp

@@ -1,6 +1,7 @@
 #include "Type.h"
-
+#include "Scope.h"
 #include "Context.h"
+#include "Semantic.h"
 #include "ErrorReporting.h"
 
 using qlow::sem::TypeId;
@@ -20,6 +21,39 @@ TypeId TypeId::toArray(void) const
 }
 
 */
+/*
+Type::NativeType::NativeType(void) = default;
+Type::NativeType::NativeType(NativeType&&) = default;
+
+Type::NativeType::NativeType(Native type) :
+    type{ type }, typeScope{ nullptr } {}
+
+Type::NativeType::~NativeType(void)
+{
+}
+*/
+
+Type::Type(Context& context, Union type) :
+    Type{ context, type, "" }
+{
+}
+
+
+Type::Type(Context& context, Union type, std::string name) :
+    name{ std::move(name) },
+    type{ std::move(type) }
+{
+    if (getKind() == Kind::NATIVE) {
+        typeScope = std::make_unique<NativeTypeScope>(context, *this);
+    }
+    else {
+        typeScope = std::make_unique<TypeScope>(context, *this);
+    }
+}
+
+
+Type::~Type(void) = default;
+
 
 Type::Kind Type::getKind(void) const
 {
@@ -77,12 +111,11 @@ bool Type::operator==(const Type& other) const
 
 qlow::sem::Class* Type::getClass(void) const
 {
-    try {
-        return std::get<ClassType>(type).classType;
-    }
-    catch(std::bad_variant_access& bva) {
+    const auto* classType = std::get_if<ClassType>(&type);
+    if (classType)
+        return classType->classType;
+    else
         return nullptr;
-    }
 }
 
 
@@ -95,25 +128,28 @@ llvm::Type* Type::getLLVMType(llvm::LLVMContext* context)
 
 Type Type::createNativeType(Context& c, std::string name, Native type)
 {
-    return Type{ Union{ NativeType{ type } }, std::move(name) };
+    return Type{ c, Union{ NativeType{ type } }, std::move(name) };
 }
 
 
 Type Type::createClassType(Context& c, Class* classType)
 {
-    return Type{ Union{ ClassType{ classType }}};
+    if (classType == nullptr) {
+        throw "invalid class type";
+    }
+    return Type{ c, Union{ ClassType{ classType }}};
 }
 
 
 Type Type::createPointerType(Context& c, TypeId pointsTo)
 {
-    return Type{ Union{ PointerType{ pointsTo }}};
+    return Type{ c, Union{ PointerType{ pointsTo }}};
 }
 
 
 Type Type::createArrayType(Context& c, TypeId pointsTo)
 {
-    return Type{ Union{ ArrayType{ pointsTo }}};
+    return Type{ c, Union{ ArrayType{ pointsTo }}};
 }
 
 

+ 25 - 6
src/sem/Type.h

@@ -2,8 +2,9 @@
 #define QLOW_SEM_TYPE_H
 
 #include <variant>
+#include <memory>
 #include <string>
-#include <climits>
+#include <limits>
 
 namespace llvm {
     class Value;
@@ -21,6 +22,8 @@ namespace qlow::sem
 
     // forward declarations to other files
     struct Class;
+    class TypeScope;
+
     class Context;
 }
 
@@ -81,6 +84,7 @@ public:
 
 private:
     std::string name;
+    std::unique_ptr<TypeScope> typeScope;
 
     struct NativeType
     {
@@ -109,20 +113,35 @@ private:
     using Union = std::variant<NativeType, ClassType, PointerType, ArrayType>;
     Union type;
 
-    inline Type(Union type) :
-        type{ type } {}
-
-    inline Type(Union type, std::string name) :
-        name{ std::move(name) }, type{ type } {}
+    inline Type(Context& context, Union type);
+    inline Type(Context& context, Union type, std::string name);
 
 public:
+    ~Type(void);
+    Type(const Type& other) = delete;
+    Type(Type&& other) = default;
+    void operator = (const Type& other) = delete;
+    Type& operator = (Type&& other) = default;
+
     Kind getKind(void) const;
     std::string asString(void) const;
     size_t hash(void) const;
 
     bool operator == (const Type& other) const;
 
+    /**
+     * @brief return the class of this type if it is a class type,
+     *        <code>nullptr</code> otherwise.
+     * @post ensures that if <code>this->getKind() == Kind::CLASS</code>,
+     *       it will not return a <code>nullptr</code>
+     */
     Class* getClass(void) const;
+    
+    /**
+     * @brief returns the type scope of this type if the type
+     *        is native, <code>nullptr</code> otherwise.
+     */
+    const TypeScope& getTypeScope(void) const;
 
     llvm::Type* getLLVMType(llvm::LLVMContext* context);