/* ----------------------------------------------------------------------------- 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 "external filter not applied in @category" { success } unittest test { \ Value:something() } concrete Value<#x> { #x defines LessThan<#x> @category something<#x> () -> () } define Value { something () {} } testcase "category param bounded on both sides" { error require compiler "#x.+bound" require compiler "[Uu]pper.+ \[Type1&Type2\]" require compiler "[Ll]ower.+ \[Type3\|Type4\]" } @value interface Type1 {} @value interface Type2 {} @value interface Type3 {} @value interface Type4 {} concrete Value<#x> { #x requires Type1 #x requires Type2 #x allows Type3 #x allows Type4 } define Value {} testcase "implicit bound from reversing another filter" { error require compiler "#x.+bound" require compiler "[Uu]pper.+ Type" require compiler "[Ll]ower.+ #y" } @value interface Type {} concrete Value<#x,#y> { #x requires Type #y requires #x } define Value {} testcase "defines filter is not an upper bound" { compiles } @type interface Type1 {} @value interface Type2 {} concrete Value<#x> { #x defines Type1 #x allows Type2 } define Value {} testcase "defines filter is not a lower bound" { compiles } @type interface Type1 {} @value interface Type2 {} concrete Value<#x> { #x defines Type1 #x requires Type2 } define Value {} testcase "function param bounded on both sides" { error require compiler "#x.+bound" } @value interface Type1 {} @value interface Type2 {} @value interface Value { call<#x> #x requires Type1 #x allows Type2 () -> () } testcase "category-level requires not met in @type call" { error require "any.+Formatted" } concrete Type<#x> { #x requires Formatted @type call () -> () } define Type { call () {} @category call2 () -> () call2 () { \ Type.call() } } testcase "category-level defines not met in @type call" { error require "any.+Equals" } concrete Type<#x> { #x defines Equals<#x> @type call () -> () } define Type { call () {} @category call2 () -> () call2 () { \ Type.call() } } testcase "category-level allows not met in @type call" { error require "all.+Int" } concrete Type<#x> { #x allows Int @type call () -> () } define Type { call () {} @category call2 () -> () call2 () { \ Type.call() } } testcase "category-level requires not met in initialization" { error require "any.+Formatted" } concrete Type<#x> { #x requires Formatted @category call () -> () } define Type { call () { \ Type{ } } } testcase "category-level defines not met in initialization" { error require "any.+Equals" } concrete Type<#x> { #x defines Equals<#x> @category call () -> () } define Type { call () { \ Type{ } } } testcase "category-level allows not met in initialization" { error require "all.+Int" } concrete Type<#x> { #x allows Int @category call () -> () } define Type { call () { \ Type{ } } } testcase "function-level requires not met in call" { error require "any.+Formatted" } concrete Type { @type call<#x> #x requires Formatted () -> () } define Type { call () {} @category call2 () -> () call2 () { \ Type.call() } } testcase "function-level defines not met in call" { error require "any.+Equals" } concrete Type { @type call<#x> #x defines Equals<#x> () -> () } define Type { call () {} @category call2 () -> () call2 () { \ Type.call() } } testcase "function-level allows not met in call" { error require "all.+Int" } concrete Type { @type call<#x> #x allows Int () -> () } define Type { call () {} @category call2 () -> () call2 () { \ Type.call() } } testcase "category-level filters meet function-level filter requirements" { compiles } concrete Type1 { @type call<#i,#j,#k> #i requires Formatted #j defines Equals<#j> #k allows Int () -> () } define Type1 { call () {} } concrete Type2<#x,#y,#z> { #x requires Formatted #y defines Equals<#y> #z allows Int @type call () -> () } define Type2 { call () { \ Type1.call<#x,#y,#z>() } } testcase "category-level filters are not checked during function-param substitution" { error require "Char.+Int" exclude "String" } concrete Type<|#x> { #x requires String } define Type {} concrete Test { @type call<#x> #x requires Int (optional Type<#x>) -> () } define Test { call (_) {} @type call2 () -> () call2 () { \ call(empty) \ call(empty) } }