/* ----------------------------------------------------------------------------- Copyright 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 "#self disallowed in @category functions" { error require "#self not found" } concrete Type { @category call () -> (#self) } define Type { call () { fail("") } } testcase "#self disallowed in @category members" { error require "#self not found" } concrete Type {} define Type { @category optional #self value <- empty } testcase "#self disallowed in @category procedures" { error require "#self not found" } concrete Type { @category call () -> () } define Type { call () { optional #self value <- empty } } testcase "#self in @type functions" { success } unittest test { Type value <- Type.create() } concrete Type { @type create () -> (#self) } define Type { create () { return Type{ } } } testcase "#self as base for @type call" { success } unittest test { Type value <- Type.create() } concrete Type { @type create () -> (Type) } define Type { create () { return #self.new() } @type new () -> (Type) new () { return Type{ } } } testcase "#self in @value functions" { success } unittest test { Type value <- Type.create().call() } concrete Type { @type create () -> (Type) @value call () -> (#self) } define Type { create () { return Type{ } } call () { return self } } testcase "#self in @value members" { success } unittest test { Type value <- Type.create(Type.create(empty)) } concrete Type { @type create (optional Type) -> (Type) } define Type { @value optional #self parent create (p) { return Type{ p } } } testcase "#self in local variables in @type procedures" { success } unittest test { Type value <- Type.create() } concrete Type { @type create () -> (Type) } define Type { create () { #self new <- Type{ } return new } } testcase "#self in local variables in @value procedures" { success } unittest test { Type value <- Type.create() } concrete Type { @type create () -> (Type) @value get () -> (Type) } define Type { create () { return Type{ } } get () { #self me <- self return me } } testcase "#self in local variables in scoped" { success } unittest test { Type value <- Type.create() } concrete Type { @type create () -> (Type) } define Type { create () { scoped { } in #self new <- Type{ } return new } } testcase "#self in reduce" { success } unittest test { Type value1 <- Type.create() Type value2 <- Type.create() \ Testing.checkEquals(value1.checkFrom>(),true) \ Testing.checkEquals(value2.checkFrom>(),false) \ Testing.checkEquals(value1.checkTo(value2),false) \ Testing.checkEquals(value2.checkTo(value1),true) } concrete Type<|#x> { @type create () -> (Type<#x>) @value checkFrom<#y> () -> (Bool) @value checkTo<#y> (#y) -> (Bool) } define Type { create () { return Type<#x>{ } } checkFrom () { return present(reduce<#self,#y>(self)) } checkTo (from) { return present(reduce<#y,#self>(from)) } } testcase "#self in typename" { success } unittest test { \ Testing.checkEquals(Type.get(),"Type>") } concrete Type<#x> { @type get () -> (String) } define Type { get () { return typename>().formatted() } } testcase "#self with type inference" { success } unittest test { \ Type.create().call("message") } concrete Type { @type create () -> (Type) @value call<#x> (#x) -> (#self) } define Type { create () { return Type{ } } call (_) { return self } } testcase "#self as an explicit function param" { success } unittest test { \ Type.create().call() } concrete Test { @type identity<#x> (#x) -> (#x) } define Test { identity (x) { return x } } concrete Type { @type create () -> (Type) @value call () -> () } define Type { create () { return Type{ } } call () { Type me <- Test.identity<#self>(self) } } testcase "#self nested in initializer type" { success } unittest test { Type> value <- Type.create().nest() } concrete Type<|#x> { @type create () -> (#self) @value nest () -> (Type<#self>) } define Type { create () { return Type<#x>{ } } nest () { return Type<#self>{ } } } testcase "#self as top-level initializer type" { success } unittest test { Type value <- Type.create() } concrete Type<|#x> { @type create () -> (#self) } define Type { create () { return #self{ } } } testcase "#self preserves type in implementations" { success } unittest withConcrete { Type value <- Type.create() \ Testing.checkEquals(value.next().prev().prev().next().next().get(),1) } unittest withIntersect { [Cell&Forward&Reverse] value <- Type.create() \ Testing.checkEquals(value.next().prev().prev().next().next().get(),1) } @value interface Cell<|#x> { get () -> (#x) } @value interface Forward { next () -> (#self) } @value interface Reverse { prev () -> (#self) } concrete Type { refines Cell refines Forward refines Reverse @type create () -> (Type) } define Type { @value Int num create () { return Type{ 0 } } get () { return num } next () { num <- num+1 return self } prev () { num <- num-1 return self } } testcase "#self preserves type in function param filters" { success } unittest test { Type value <- Helper.new() \ Testing.checkEquals((value `Advance.by` 3).get(),3) } @value interface Forward { next () -> (#self) } concrete Helper { @type new<#x> #x defines Default () -> (#x) } define Helper { new () { return #x.default() } } concrete Advance { @type by<#x> #x requires Forward (#x,Int) -> (#x) } define Advance { by (x,i) (x2) { x2 <- x scoped { Int count <- 0 } in while (count < i) { x2 <- x2.next() } update { count <- count+1 } } } concrete Type { refines Forward defines Default @value get () -> (Int) } define Type { @value Int num default () { return Type{ 0 } } get () { return num } next () { return Type{ num+1 } } } testcase "#self at top level of param filter" { compiles } concrete Type<#x> { #x allows #self } define Type {} testcase "#self nested in param filter" { compiles } concrete Type<#x> { #x requires Writer<#self> #x defines Equals<#self> } define Type {} @value interface Writer<#x|> {} testcase "#self nested in inheritance" { compiles } concrete Type<#x> { refines Gettable<#self> defines Creator<#self> } define Type { get () { return self } create () { return #self{ } } } @value interface Gettable<|#x> { get () -> (#x) } @type interface Creator<|#x> { create () -> (#x) } testcase "#self allowed in category param filters" { compiles } concrete Type1<#x> { #x allows #self } define Type1 {} concrete Type2<#x> { #x requires #self } define Type2 {} testcase "#self allowed in covavariant position of function param filter" { compiles } @value interface Type { call<#x> #x allows #self () -> () } testcase "#self disallowed in contravariant position of function param filter" { error require "#self.+contravariant" } @value interface Type { call<#x> #x requires #self () -> () }