Commits

hvellyr committed d7eadbd

Implement compare operator for Integers and as ducktype operation

Comments (0)

Files changed (4)

bootstrap/codegen-binnode.cpp

       return wrapBool(builder().CreateICmpUGE(coleft, coright, "getmp"),
                       node->type());
 
+  case kOpCompare:
+    coleft = convertToPlainInt(node->type(), node->left(), left);
+    coright = convertToPlainInt(node->type(), node->right(), right);
+    return wrapInt(builder().CreateSub(coleft, coright, "cmptmp"),
+                   node->type());
   default:
     fprintf(stderr, "invalid binary operator: %d", node->op());
     return NULL;
   case kOpGreaterEqual:
     return wrapBool(builder().CreateICmpUGE(coleft, coright, "gechr"),
                     node->type());
+  case kOpCompare:
+    return wrapInt(builder().CreateSub(coleft, coright, "cmpchr"),
+                   node->type());
 
   default:
     fprintf(stderr, "invalid binary operator for char: %d", node->op());
   case kOpGreaterEqual:
     return codegenOpDuckTypeBinary(node, Names::kLangGreaterEqualQ, Type::newBool());
   case kOpCompare:
-    return codegenOpDuckTypeBinary(node, Names::kLangCompare, Type::newAny());
+    return codegenOpDuckTypeBinary(node, Names::kLangCompare, Type::newInt32());
 
   default:
     fprintf(stderr, "binary operator not supported in ducktyping yet: %d", node->op());

bootstrap/typify.cpp

       break;
 
     case kOpCompare:
-      // TODO: check that left and right type are comparable
-      node->setType(Type::newInt32());
-      annotateTypeConv(node->left(), leftty);
-      annotateTypeConv(node->right(), leftty);
+      if ( leftty.isAny() || rightty.isAny() ||
+           (leftty.isAnySignedInt() && rightty.isAnySignedInt()) ||
+           (leftty.isAnyUInt() && rightty.isAnyUInt()) ||
+           (leftty.isAnyFloat() && rightty.isAnyFloat()) ||
+           (leftty.isRational() && rightty.isRational()) ||
+           (leftty.isComplex() && rightty.isComplex()) ||
+           (leftty.isNumber() && rightty.isNumber()) ||
+           isSameType(leftty, rightty, node->scope(), node->srcpos()) )
+      {
+        node->setType(Type::newInt32());
+        annotateTypeConv(node->left(), leftty);
+        annotateTypeConv(node->right(), leftty);
+        annotateTypeConv(node, node->type());
+        return;
+      }
+
+      errorf(node->srcpos(), E_BinaryTypeMismatch,
+             "incompatible types in binary comparison (compare)");
+      node->setType(Type::newAny());
       annotateTypeConv(node, node->type());
       break;
 

lib/lang/impl/numbers.h7

 
 
 
+def macro compare-integer-1
+{
+  { compare-integer-1(?retv:name, ?lhs:name, ?other:name, ?op:operator) } ->
+    { match (?other) {
+                | j : Int8   -> ?retv = ?lhs ?op j
+                | j : Int16  -> ?retv = ?lhs ?op j
+                | j : Int32  -> ?retv = ?lhs ?op j
+                | j : Int64  -> ?retv = ?lhs ?op j
+
+                |   : Any -> 0         -- raise TypeException
+                } }
+}
+
+def macro compare-integer-2
+{
+  { compare-integer-2(?retv:name, ?lhs:name, ?other:name, ?op:operator) } ->
+    { match (?other) {
+                | j : UInt8  -> ?retv = ?lhs ?op j
+                | j : UInt16 -> ?retv = ?lhs ?op j
+                | j : UInt32 -> ?retv = ?lhs ?op j
+                | j : UInt64 -> ?retv = ?lhs ?op j
+
+                |   : Any -> 0         -- raise TypeException
+                } }
+}
+
+def macro compare-integer
+{
+  { compare-integer(?lvalue:name, ?op:operator, ?rvalue:name) } ->
+    { {
+        let t : Int = 0
+        match (?lvalue) {
+        | i : Int8  -> compare-integer-1(t, i, ?rvalue, ?op)
+        | i : Int16 -> compare-integer-1(t, i, ?rvalue, ?op)
+        | i : Int32 -> compare-integer-1(t, i, ?rvalue, ?op)
+        | i : Int64 -> compare-integer-1(t, i, ?rvalue, ?op)
+
+        | i : UInt8  -> compare-integer-2(t, i, ?rvalue, ?op)
+        | i : UInt16 -> compare-integer-2(t, i, ?rvalue, ?op)
+        | i : UInt32 -> compare-integer-2(t, i, ?rvalue, ?op)
+        | i : UInt64 -> compare-integer-2(t, i, ?rvalue, ?op)
+
+        |   : Any -> 0                        -- raise TypeException
+        }
+        t
+    } }
+}
+
+def lang|compare(one @ Integer, two @ Integer) : Int
+  compare-integer(one, <=>, two)
+
+
+
+
 
 
 -- unary

tests/compile/op-int-04.h7

+-- test add operator on weakly typed values
+
+import "lang/assert.h7"
+
+def assert-compare-less(a, b) : Bool
+  let t = a <=> b
+  assert(t < 0)
+
+def assert-compare-less-int(a : Int, b : Int) : Bool
+  let t = a <=> b
+  assert(t < 0)
+
+def test-compare() : Any
+  assert-compare-less-int(5, 6)
+  assert-compare-less(6, 15)
+  true
+
+
+def app|main()
+  test-compare()
+
+  0