/* ----------------------------------------------------------------------------- Copyright 2020-2021 Kevin P. Barry Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------------------------------------------------------------- */ // Author: Kevin P. Barry [ta0kira@gmail.com] testcase "simple inference" { success } unittest test { Int value <- Test.get(10) } concrete Test { @type get<#x> (#x) -> (#x) } define Test { get (x) { return x } } testcase "inference mismatch" { error require "get" require "String" require "Int" } unittest test { String value <- Test.get(10) } concrete Test { @type get<#x> (#x) -> (#x) } define Test { get (x) { return x } } testcase "nested inference" { success } unittest test { Type value <- Test.get(Type.create()) } concrete Type<#x> { @type create () -> (Type<#x>) } define Type { create () { return Type<#x>{ } } } concrete Test { @type get<#x> (Type<#x>) -> (Type<#x>) } define Test { get (x) { return x } } testcase "simple inference with qualification" { success } unittest test { Int value <- Test.get(10) } concrete Test { @type get<#x> (#x) -> (#x) } define Test { get (x) { return x } } testcase "inference mismatch with qualification" { error require "get" require "String" require "Int" } unittest test { String value <- Test.get(10) } concrete Test { @type get<#x> (#x) -> (#x) } define Test { get (x) { return x } } testcase "nested inference with qualification" { success } unittest test { Type value <- Test.get(Type.create()) } concrete Type<#x> { @type create () -> (Type<#x>) } define Type { create () { return Type<#x>{ } } } concrete Test { @type get<#x> (Type<#x>) -> (Type<#x>) } define Test { get (x) { return x } } testcase "inference conflict" { error require "get" require "#x" } unittest test { Type value <- Test.get(Type.create(),"bad") } concrete Type<#x> { @type create () -> (Type<#x>) } define Type { create () { return Type<#x>{ } } } concrete Test { @type get<#x> (Type<#x>,#x) -> (Type<#x>) } define Test { get (x,_) { return x } } testcase "elimination by filter" { error require "get" require "#x" require "Formatted.+String" } unittest test { \ Test.get("value") } concrete Test { @type get<#x> #x allows Formatted (#x) -> (#x) } define Test { get (x) { return x } } testcase "elimination by filter without param" { error require "get" require "#x" require "Formatted.+String" } unittest test { \ Test.get("value") } concrete Test { @type get<#y,#x> #x allows #y (#x) -> (#x) } define Test { get (x) { return x } } testcase "elimination by filter including param" { error require "get" require "#x" require "String.+Type" require "Type.+String" } unittest test { \ Test.get(Type.create()) } concrete Type<#x> { @type create () -> (Type<#x>) } define Type { create () { return Type<#x>{ } } } concrete Test { @type get<#x> #x allows Type<#x> (#x) -> (#x) } define Test { get (x) { return x } } testcase "clashing param filter in the same scope" { success } unittest test { \ Test.get1() } concrete Test { @type get1<#x> #x requires Int () -> () } define Test { get1 () { String value <- get2("message") } @type get2<#x> (#x) -> (#x) get2 (x) { return x } } testcase "mutually dependent inferences" { error require "get" require "#x.+Int" require "#y.+String" } unittest test { Type x <- Type.create() Type y <- Type.create() \ Test.get(x,y) } concrete Type<#x> { @type create () -> (Type<#x>) } define Type { create () { return Type<#x>{ } } } concrete Test { @type get<#x,#y> #x requires Type<#y> #y requires Type<#x> (#x,#y) -> () } define Test { get (_,_) {} } testcase "all/any as valid lower/upper bounds" { compiles } concrete Test { @type call<#x,#y> (Convert<#x,#y>) -> (#x,#y) } define Test { call (_) { fail("this allows faking the return") } @value run () -> () run () { any x1, all y1 <- call(Convert.create()) all x2, any y2 <- call(Convert.create()) } } concrete Convert<#x|#y> { @type create () -> (#self) } define Convert { create () { return #self{ } } }