aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compiler/compiler.go23
-rw-r--r--src/runtime/string.go18
-rw-r--r--testdata/binop.go23
-rw-r--r--testdata/binop.txt20
4 files changed, 74 insertions, 10 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go
index efbdbccda..f14193a8f 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -3054,7 +3054,7 @@ func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value) (
} else if typ.Info()&types.IsFloat != 0 {
// Operations on floats
switch op {
- case token.ADD:
+ case token.ADD: // +
return c.builder.CreateFAdd(x, y, ""), nil
case token.SUB: // -
return c.builder.CreateFSub(x, y, ""), nil
@@ -3102,14 +3102,23 @@ func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value) (
} else if typ.Info()&types.IsString != 0 {
// Operations on strings
switch op {
- case token.ADD:
+ case token.ADD: // +
return c.createRuntimeCall("stringConcat", []llvm.Value{x, y}, ""), nil
- case token.EQL, token.NEQ: // ==, !=
+ case token.EQL: // ==
+ return c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, ""), nil
+ case token.NEQ: // !=
result := c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, "")
- if op == token.NEQ {
- result = c.builder.CreateNot(result, "")
- }
- return result, nil
+ return c.builder.CreateNot(result, ""), nil
+ case token.LSS: // <
+ return c.createRuntimeCall("stringLess", []llvm.Value{x, y}, ""), nil
+ case token.LEQ: // <=
+ result := c.createRuntimeCall("stringLess", []llvm.Value{y, x}, "")
+ return c.builder.CreateNot(result, ""), nil
+ case token.GTR: // >
+ result := c.createRuntimeCall("stringLess", []llvm.Value{x, y}, "")
+ return c.builder.CreateNot(result, ""), nil
+ case token.GEQ: // >=
+ return c.createRuntimeCall("stringLess", []llvm.Value{y, x}, ""), nil
default:
return llvm.Value{}, errors.New("todo: binop on string: " + op.String())
}
diff --git a/src/runtime/string.go b/src/runtime/string.go
index 540c6410f..f3e42df7e 100644
--- a/src/runtime/string.go
+++ b/src/runtime/string.go
@@ -32,6 +32,24 @@ func stringEqual(x, y string) bool {
return true
}
+// Return true iff x < y.
+//go:nobounds
+func stringLess(x, y string) bool {
+ l := len(x)
+ if m := len(y); m < l {
+ l = m
+ }
+ for i := 0; i < l; i++ {
+ if x[i] < y[i] {
+ return true
+ }
+ if x[i] > y[i] {
+ return false
+ }
+ }
+ return len(x) < len(y)
+}
+
// Add two strings together.
func stringConcat(x, y _string) _string {
if x.length == 0 {
diff --git a/testdata/binop.go b/testdata/binop.go
index 5526d13be..24774aade 100644
--- a/testdata/binop.go
+++ b/testdata/binop.go
@@ -1,13 +1,30 @@
package main
func main() {
- // string equality
+ println("string equality")
println(a == "a")
println(a == "b")
println(a != "a")
println(a != "b")
+ println("string inequality")
+ println(a > "b")
+ println("b" > a)
+ println("b" > "b")
+ println(a <= "b")
+ println("b" <= a)
+ println("b" <= "b")
+ println(a > "b")
+ println("b" > a)
+ println("b" > "b")
+ println(a <= "b")
+ println("b" <= a)
+ println("b" <= "b")
+ println(a < "aa")
+ println("aa" < a)
+ println("ab" < "aa")
+ println("aa" < "ab")
- // struct equality
+ println("struct equality")
println(s1 == Struct1{3, true})
println(s1 == Struct1{4, true})
println(s1 == Struct1{3, false})
@@ -17,7 +34,7 @@ func main() {
println(s1 != Struct1{3, false})
println(s1 != Struct1{4, false})
- // blank fields in structs
+ println("blank fields in structs")
println(s2 == Struct2{"foo", 0.0, 5})
println(s2 == Struct2{"foo", 0.0, 7})
println(s2 == Struct2{"foo", 1.0, 5})
diff --git a/testdata/binop.txt b/testdata/binop.txt
index ef3bec46d..1e2f40e70 100644
--- a/testdata/binop.txt
+++ b/testdata/binop.txt
@@ -1,7 +1,26 @@
+string equality
true
false
false
true
+string inequality
+false
+true
+false
+true
+false
+true
+false
+true
+false
+true
+false
+true
+true
+false
+false
+true
+struct equality
true
false
false
@@ -10,6 +29,7 @@ false
true
true
true
+blank fields in structs
true
false
true