/* ----------------------------------------------------------------------------- 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 "Issue #73 is fixed" { // https://github.com/ta0kira/zeolite/issues/73 success } unittest test { \ Type2.call() } concrete Type1<#x> { @type call<#y> (#x) -> () } define Type1 { call (_) {} } concrete Type2<#y> { @type call () -> () } define Type2 { call () { // Value<#y> gets subbed in for #x, so call is re-parameterized with an // argument of type Value<#y>. When the compiler processes call, it // looks for #y, which it finds; however, it's a different #y. \ Type1>.call(Value<#y>.create()) } } concrete Value<#z> { @type create () -> (Value<#z>) } define Value { create () { return Value<#z>{ } } } testcase "Issue #73 (2) is fixed" { // https://github.com/ta0kira/zeolite/issues/73 error require "from Base" require "#x hides" require "call1" exclude "call2" } @value interface Base { call1<#x> (#x) -> () call2<#x> (#x) -> () } concrete Child<#x> { refines Base // call1 is inherited with #x, which conflicts with #x in Child. // @value call1<#y> (#y) -> () // call2 explicitly overrides #x with #y. @value call2<#y> (#y) -> () } define Child { call1 (_) {} call2 (_) {} } testcase "Issue #73 is not re-broken by #self" { // https://github.com/ta0kira/zeolite/issues/73 success } unittest test { \ Type2.call() } concrete Type1<|#x> { @type create<#y> () -> (#self) } define Type1 { create () { return #self{ } } } concrete Type2<#y> { @type call () -> () } define Type2 { call () { // Type1<#y> is substituted in for #self, putting #y in the return type. // This is a different #y than create's own #y, and so it should not be // substituted with Int. Type1<#y> value <- Type1<#y>.create() } } testcase "Issue #121 is fixed" { // https://github.com/ta0kira/zeolite/issues/121 success } unittest test { Int count <- 0 scoped { count <- count+1 } cleanup { // Previously, the scoped block was prepended to the cleanup block, due to // a change that precompiled scoped+in to allow use of named returns. count <- count+1 } in { count <- count+1 } // The count here would be 4 if scoped was prepended to cleanup. \ Testing.checkEquals(count,3) } testcase "Issue #122 is fixed: break" { // https://github.com/ta0kira/zeolite/issues/122 error require "cleanup" require "message.+initialized" } unittest test { \ Type.call() } concrete Type { @type call () -> (String) } define Type { call () (message) { while (true) { cleanup { fail(message) } in { if (true) { // There should be an error here (referring back to fail(message) // above) because message might not be set. break } message <- "message" } } return "return" } } testcase "Issue #122 is fixed: continue" { // https://github.com/ta0kira/zeolite/issues/122 error require "cleanup" require "message.+initialized" } unittest test { \ Type.call() } concrete Type { @type call () -> (String) } define Type { call () (message) { while (true) { cleanup { fail(message) } in { if (true) { // There should be an error here (referring back to fail(message) // above) because message might not be set. continue } message <- "message" } } return "return" } } testcase "Issue #126 is fixed" { // https://github.com/ta0kira/zeolite/issues/126 crash require "message,12345,false" } unittest test { \ Type.call() } concrete Type { @type call () -> (String,Int,Bool) } define Type { call () (x,y,z) { cleanup { // Primitive variables y and z need to be explicitly set separately from // the return tuple, since the former are stored separately. fail(x + "," + y.formatted() + "," + z.formatted()) } in return "message", 12345, false } } testcase "Issue #127 is fixed: if" { // https://github.com/ta0kira/zeolite/issues/127 error require "cleanup" require "message.+initialized" } unittest test { \ Type.call() } concrete Type { @type call () -> (String) } define Type { call () (message) { cleanup { // Using message on the right side of && makes sure that message is still // counted as being required, despite possible short-circuiting. if (true && message != "message") { fail("failed") } } in {} return "return" } } testcase "Issue #127 is fixed: while" { // https://github.com/ta0kira/zeolite/issues/127 error require "cleanup" require "message.+initialized" } unittest test { \ Type.call() } concrete Type { @type call () -> (String) } define Type { call () (message) { cleanup { // Using message on the right side of && makes sure that message is still // counted as being required, despite possible short-circuiting. while (true && message != "message") { fail("failed") } } in {} return "return" } }