compiler: implement binop string: <, <=, >, >=
Include unit tests.
Этот коммит содержится в:
родитель
76d04990f4
коммит
b1cf69a523
4 изменённых файлов: 74 добавлений и 10 удалений
|
@ -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 {
|
} else if typ.Info()&types.IsFloat != 0 {
|
||||||
// Operations on floats
|
// Operations on floats
|
||||||
switch op {
|
switch op {
|
||||||
case token.ADD:
|
case token.ADD: // +
|
||||||
return c.builder.CreateFAdd(x, y, ""), nil
|
return c.builder.CreateFAdd(x, y, ""), nil
|
||||||
case token.SUB: // -
|
case token.SUB: // -
|
||||||
return c.builder.CreateFSub(x, y, ""), nil
|
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 {
|
} else if typ.Info()&types.IsString != 0 {
|
||||||
// Operations on strings
|
// Operations on strings
|
||||||
switch op {
|
switch op {
|
||||||
case token.ADD:
|
case token.ADD: // +
|
||||||
return c.createRuntimeCall("stringConcat", []llvm.Value{x, y}, ""), nil
|
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}, "")
|
result := c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, "")
|
||||||
if op == token.NEQ {
|
return c.builder.CreateNot(result, ""), nil
|
||||||
result = c.builder.CreateNot(result, "")
|
case token.LSS: // <
|
||||||
}
|
return c.createRuntimeCall("stringLess", []llvm.Value{x, y}, ""), nil
|
||||||
return result, 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:
|
default:
|
||||||
return llvm.Value{}, errors.New("todo: binop on string: " + op.String())
|
return llvm.Value{}, errors.New("todo: binop on string: " + op.String())
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,24 @@ func stringEqual(x, y string) bool {
|
||||||
return true
|
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.
|
// Add two strings together.
|
||||||
func stringConcat(x, y _string) _string {
|
func stringConcat(x, y _string) _string {
|
||||||
if x.length == 0 {
|
if x.length == 0 {
|
||||||
|
|
23
testdata/binop.go
предоставленный
23
testdata/binop.go
предоставленный
|
@ -1,13 +1,30 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// string equality
|
println("string equality")
|
||||||
println(a == "a")
|
println(a == "a")
|
||||||
println(a == "b")
|
println(a == "b")
|
||||||
println(a != "a")
|
println(a != "a")
|
||||||
println(a != "b")
|
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{3, true})
|
||||||
println(s1 == Struct1{4, true})
|
println(s1 == Struct1{4, true})
|
||||||
println(s1 == Struct1{3, false})
|
println(s1 == Struct1{3, false})
|
||||||
|
@ -17,7 +34,7 @@ func main() {
|
||||||
println(s1 != Struct1{3, false})
|
println(s1 != Struct1{3, false})
|
||||||
println(s1 != Struct1{4, 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, 5})
|
||||||
println(s2 == Struct2{"foo", 0.0, 7})
|
println(s2 == Struct2{"foo", 0.0, 7})
|
||||||
println(s2 == Struct2{"foo", 1.0, 5})
|
println(s2 == Struct2{"foo", 1.0, 5})
|
||||||
|
|
20
testdata/binop.txt
предоставленный
20
testdata/binop.txt
предоставленный
|
@ -1,7 +1,26 @@
|
||||||
|
string equality
|
||||||
true
|
true
|
||||||
false
|
false
|
||||||
false
|
false
|
||||||
true
|
true
|
||||||
|
string inequality
|
||||||
|
false
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
true
|
||||||
|
false
|
||||||
|
false
|
||||||
|
true
|
||||||
|
struct equality
|
||||||
true
|
true
|
||||||
false
|
false
|
||||||
false
|
false
|
||||||
|
@ -10,6 +29,7 @@ false
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
|
blank fields in structs
|
||||||
true
|
true
|
||||||
false
|
false
|
||||||
true
|
true
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче