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 | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Marc-Antoine Ruel
						Marc-Antoine Ruel