瀏覽代碼

trying to get field acces to work

Nicolas Winkler 6 年之前
父節點
當前提交
a474769630
共有 8 個文件被更改,包括 155 次插入14 次删除
  1. 5 0
      src/AstVisitor.cpp
  2. 36 11
      src/CodegenVisitor.cpp
  3. 27 0
      src/Type.cpp
  4. 5 0
      src/Type.h
  5. 1 1
      src/parser.y
  6. 3 2
      src/test.qlw
  7. 36 0
      vim/indent/qlow.vim
  8. 42 0
      vim/syntax/qlow.vim

+ 5 - 0
src/AstVisitor.cpp

@@ -179,6 +179,11 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& as
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope)
 {
+    std::unique_ptr<sem::SemanticObject> target = nullptr;
+    if (ast.target) {
+        target = ast.target->accept(*this, scope);
+    }
+    
     auto* method = scope.getMethod(ast.name);
     auto* var = scope.getVariable(ast.name);
     

+ 36 - 11
src/CodegenVisitor.cpp

@@ -29,34 +29,47 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::BinaryOperatio
     auto [left, leftType] = binop.left->accept(*this, builder);
     auto [right, rightType] = binop.right->accept(*this, builder);
     
-    if (!leftType->equals(Type::INTEGER) || !rightType->equals(Type::INTEGER))
+    
+    if (!leftType->isNativeType() || !rightType->isNativeType())
         throw "invalid types in BinaryOperation";
     
+    
     if (left == nullptr) {
         printf("WOW: %s\n", binop.left->toString().c_str());
     }
     
     
+    Value* implicitelyCastedRight = right;
+    if (!leftType->equals(rightType))
+        implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType)->generateImplicitCast(right);
+    
+    if (dynamic_cast<sem::NativeType*>(leftType)->isIntegerType()) {
+        // TODO allow integer operations
+    }
+    
+    
     // TODO insert type checks
     switch (binop.op) {
         case ast::Operation::Operator::PLUS:
-            return { builder.CreateAdd(left, right, "add"), Type::INTEGER };
+            return { builder.CreateAdd(left, right, "add"), leftType };
         case ast::Operation::Operator::MINUS:
-            return { builder.CreateSub(left, right, "sub"), Type::INTEGER };
+            return { builder.CreateSub(left, right, "sub"), leftType };
         case ast::Operation::Operator::ASTERISK:
-            return { builder.CreateMul(left, right, "mul"), Type::INTEGER };
+            return { builder.CreateMul(left, right, "mul"), leftType };
         case ast::Operation::Operator::SLASH:
-            return { builder.CreateSDiv(left, right, "add"), Type::INTEGER };
-        case ast::Operation::Operator::EQUALS:
-            return { builder.CreateICmpEQ(left, right, "equals"), Type::BOOLEAN };
-        case ast::Operation::Operator::NOT_EQUALS:
-            return { builder.CreateICmpNE(left, right, "not_equals"), Type::BOOLEAN };
+            return { builder.CreateSDiv(left, right, "sdiv"), leftType };
+            
         case ast::Operation::Operator::AND:
             return { builder.CreateAnd(left, right, "and"), Type::BOOLEAN };
         case ast::Operation::Operator::OR:
             return { builder.CreateOr(left, right, "or"), Type::BOOLEAN };
         case ast::Operation::Operator::XOR:
             return { builder.CreateXor(left, right, "xor"), Type::BOOLEAN };
+            
+        case ast::Operation::Operator::EQUALS:
+            return { builder.CreateICmpEQ(left, right, "equals"), Type::BOOLEAN };
+        case ast::Operation::Operator::NOT_EQUALS:
+            return { builder.CreateICmpNE(left, right, "not_equals"), Type::BOOLEAN };
     }
 }
 
@@ -197,16 +210,28 @@ llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
 llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         qlow::gen::FunctionGenerator& fg)
 {
+    Logger& logger = Logger::getInstance();
     llvm::IRBuilder<> builder(fg.getContext());
     builder.SetInsertPoint(fg.getCurrentBlock());
     auto [val, type] = assignment.value->accept(fg.expressionVisitor, builder);
     if (auto* targetVar =
         dynamic_cast<sem::LocalVariableExpression*>(assignment.target.get()); targetVar) {
+        logger.debug() << "assigning to LocalVariableExpression" << std::endl;
         builder.CreateStore(val, targetVar->var->allocaInst);
     }
-    else
+    else if (auto* targetVar =
+        dynamic_cast<sem::FeatureCallExpression*>(assignment.target.get()); targetVar) {
+        
+        logger.debug() << "assigning to FeatureCallExpression" << std::endl;
+    }
+    else {
+        
+        logger.debug() << "assigning to instance of " << assignment.target->toString() << std::endl;
         throw "only local variables are assignable at the moment";
-    return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5123.0));
+    }
+    
+    return nullptr;
+    //return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5123.0));
 }
 
 

+ 27 - 0
src/Type.cpp

@@ -61,6 +61,27 @@ bool sem::ArrayType::equals(const Type* other) const
 }
 
 
+bool sem::NativeType::isIntegerType(void) const
+{
+    switch(type) {
+        case INTEGER:
+        case INT8:
+        case INT16:
+        case INT32:
+        case INT64:
+        case INT128:
+        case UINT8:
+        case UINT16:
+        case UINT32:
+        case UINT64:
+        case UINT128:
+            return true;
+        default:
+            return false;
+    }
+}
+
+
 llvm::Type* sem::NativeType::getLlvmType (llvm::LLVMContext& context) const
 {
     switch (type) {
@@ -115,3 +136,9 @@ bool sem::NativeType::equals(const sem::Type* other) const
     }
 }
 
+
+llvm::Value* sem::NativeType::generateImplicitCast(llvm::Value* value)
+{
+    // TODO implement
+}
+

+ 5 - 0
src/Type.h

@@ -112,8 +112,13 @@ public:
     inline bool isNativeType(void) const override { return true; }
     inline bool isArrayType(void) const override { return false; }
     
+    bool isIntegerType(void) const;
+    
     llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
     virtual bool equals(const sem::Type* other) const;
+    
+    /// cast an llvm::Value from another native type to this one
+    llvm::Value* generateImplicitCast(llvm::Value* value);
 };
 
 

+ 1 - 1
src/parser.y

@@ -165,6 +165,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %destructor { } <topLevel> // don't delete everything ;)
 %destructor { if ($$) delete $$; } <*>
 
+%left DOT
 %left ASTERISK SLASH
 %left PLUS MINUS
 %left EQUALS
@@ -566,7 +567,6 @@ newArrayExpression:
         
     };
 
-
 assignmentStatement:
     expression ASSIGN expression {
         $$ = new AssignmentStatement(std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3), @$);

+ 3 - 2
src/test.qlw

@@ -1,4 +1,3 @@
-
 fast_fibonacci(i: Integer): Integer do
     a: Integer
     b: Integer
@@ -18,11 +17,13 @@ end
 
 extern do_shit
 
+
 bignumbers do
     a: Int128
     b: Int128
+    c: Int64
 
-    b := b + a
+    b := a + c
 end
 
 main do

+ 36 - 0
vim/indent/qlow.vim

@@ -0,0 +1,36 @@
+" indent/qlow.vim
+if exists("b:did_indent")
+   finish
+endif
+let b:did_indent = 1
+setlocal indentexpr=QlowIndent()
+setlocal nolisp
+setlocal nosmartindent
+setlocal nocindent
+setlocal autoindent
+setlocal comments=:--
+setlocal indentkeys+==end,=do,=class
+
+let b:undo_indent = "setl smartindent< indentkeys< indentexpr< autoindent< comments< "
+
+function! QlowIndent()
+  let line = getline(v:lnum)
+  let previousNum = prevnonblank(v:lnum - 1)
+  let previous = getline(previousNum)
+
+
+  let ind = indent(previousNum)
+  "if previous =~ "{" && previous !~ "}" && line !~ "}" && line !~ ":$"
+  if previous =~ "class" || previous =~ "do"
+      let ind = ind + &shiftwidth
+  endif
+
+  if getline(v:lnum) =~ '^\s*end'
+      let ind = ind - &shiftwidth
+  endif
+
+  return ind
+endfunction
+
+
+

+ 42 - 0
vim/syntax/qlow.vim

@@ -0,0 +1,42 @@
+" Vim syntax file
+" Language: Qlow Programming Language
+" Maintainer: Nicolas Winkler
+" Latest Revision: 07 March 2018
+
+
+if exists("b:current_syntax")
+  finish
+endif
+
+
+
+syn keyword keywordy class do end if while return extern
+syn keyword typey Integer Boolean
+syn keyword typey String Char 
+syn keyword typey Int8 Int16 Int32 Int64 Int128 UInt8 UInt16 UInt32 UInt64 UInt128
+syn keyword typey Float32 Float64
+
+
+syntax match identifiery "[a-zA-Z][a-zA-Z0-9]*"
+syntax match numbery "\d\+"
+syntax match stringy "\".\+\""
+syntax match commenty "//.*"
+syntax region multicommenty start="/\*"  end="\*/" contains=multicommenty
+
+syntax keyword operatory not or and xor
+syntax match operatory "\v\:\="
+
+
+hi def link identifiery None
+hi def link numbery Number
+hi def link stringy String
+hi def link keywordy Keyword
+hi def link operatory Operator 
+hi def link typey Type
+hi def link commenty Comment
+hi def link multicommenty Comment
+hi Operator guifg=#FF0000 guibg=NONE gui=none
+
+let b:current_syntax = "qlw"
+
+