(t *testing.T)
| 82 | } |
| 83 | |
| 84 | func TestFunctionMerge(t *testing.T) { |
| 85 | size := Function("size", |
| 86 | Overload("size_map", []*Type{MapType(TypeParamType("K"), TypeParamType("V"))}, IntType), |
| 87 | Overload("size_list", []*Type{ListType(TypeParamType("V"))}, IntType), |
| 88 | Overload("size_string", []*Type{StringType}, IntType), |
| 89 | Overload("size_bytes", []*Type{BytesType}, IntType), |
| 90 | MemberOverload("map_size", []*Type{MapType(TypeParamType("K"), TypeParamType("V"))}, IntType), |
| 91 | MemberOverload("list_size", []*Type{ListType(TypeParamType("V"))}, IntType), |
| 92 | MemberOverload("string_size", []*Type{StringType}, IntType), |
| 93 | MemberOverload("bytes_size", []*Type{BytesType}, IntType), |
| 94 | SingletonUnaryBinding(func(arg ref.Val) ref.Val { |
| 95 | return arg.(traits.Sizer).Size() |
| 96 | }, traits.SizerType), |
| 97 | ) |
| 98 | // Note, the size() implementation is inherited from the singleton implementation for the size function. |
| 99 | // It is possible to redefine the singleton, but the singleton approach is incompatible with specialized |
| 100 | // overloads as the singleton is compatible with the parse-only approach and compiled approach; but |
| 101 | // a mix of singleton and specialized overloads might result in a singleton which does not encompass |
| 102 | // dynamic dispatch to all possible overloads. |
| 103 | sizeExt := Function("size", |
| 104 | Overload("size_vector", []*Type{OpaqueType("vector", TypeParamType("V"))}, IntType), |
| 105 | MemberOverload("vector_size", []*Type{OpaqueType("vector", TypeParamType("V"))}, IntType)) |
| 106 | |
| 107 | vectorExt := Function("vector", |
| 108 | Overload("vector_list", []*Type{ListType(TypeParamType("V"))}, OpaqueType("vector", TypeParamType("V")), |
| 109 | UnaryBinding(func(list ref.Val) ref.Val { |
| 110 | return list |
| 111 | }))) |
| 112 | |
| 113 | eq := Function(operators.Equals, |
| 114 | Overload(operators.Equals, []*Type{TypeParamType("T"), TypeParamType("T")}, BoolType, |
| 115 | BinaryBinding(func(lhs, rhs ref.Val) ref.Val { |
| 116 | return lhs.Equal(rhs) |
| 117 | }))) |
| 118 | |
| 119 | e, err := NewCustomEnv(size, sizeExt, vectorExt, eq) |
| 120 | if err != nil { |
| 121 | t.Fatalf("NewCustomEnv() failed: %v", err) |
| 122 | } |
| 123 | ast, iss := e.Compile(`[[0].size() == 1, |
| 124 | {'a': true, 'b': false}.size() == 2, |
| 125 | 'hello'.size() == 5, |
| 126 | b'hello'.size() == 5, |
| 127 | vector([1.2, 2.3, 3.4]).size() == 3]`) |
| 128 | if iss.Err() != nil { |
| 129 | t.Fatalf("Compile() errored: %v", iss.Err()) |
| 130 | } |
| 131 | if !reflect.DeepEqual(ast.OutputType(), ListType(BoolType)) { |
| 132 | t.Errorf("Compile() produced a %v, wanted bool", ast.OutputType()) |
| 133 | } |
| 134 | if ast.OutputType().String() != "list(bool)" { |
| 135 | t.Errorf("ast.OutputType().String() produced %s, wanted list(bool)", ast.OutputType()) |
| 136 | } |
| 137 | prg, err := e.Program(ast) |
| 138 | if err != nil { |
| 139 | t.Fatalf("e.Program(ast) failed: %v", err) |
| 140 | } |
| 141 | out, _, err := prg.Eval(NoVars()) |
nothing calls this directly
no test coverage detected