/* ----------------------------------------------------------------------------- Copyright 2021-2022 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 "unused deferred" { compiles } unittest test { Int value <- defer } testcase "assigned deferred" { compiles } unittest test { Int value <- defer value <- 1 \ value } testcase "defer new" { error require "value" require "initialized" } unittest test { Int value <- defer \ value } testcase "defer existing" { error require "value" require "initialized" } unittest test { Int value <- 1 value <- defer \ value } testcase "defer does not unset members" { success } concrete Test { @type new () -> (#self) @value deferMembers () -> () @value getValueMember () -> (String) @value getCategoryMember () -> (String) } define Test { @category String categoryMember <- "abc" @value String valueMember new () { return #self{ "def" } } deferMembers () { categoryMember, valueMember <- defer } getValueMember () { return valueMember } getCategoryMember () { return categoryMember } } unittest test { Test test <- Test.new() \ Testing.checkEquals(test.getCategoryMember(), "abc") \ Testing.checkEquals(test.getValueMember(), "def") } testcase "multiple deferred" { error require "value1" require "initialized" exclude "value0" } unittest test { Int value1 <- 1 Int value2, value1 <- defer \ value1 } testcase "cannot defer _" { error require "defer" require "discard" } unittest test { _ <- defer } testcase "can defer @value member" { error require "value" require "initialized" } concrete Type { } define Type { @value Int value @value call () -> () call () { value <- defer \ value } } testcase "can defer @category member" { error require "value" require "initialized" } concrete Type { } define Type { @category Int value <- 1 @value call () -> () call () { value <- defer \ value } } testcase "cannot defer function argument" { error require "defer" require "value" require "read-only" } concrete Type { } define Type { @value call (Int) -> () call (value) { value <- defer } } testcase "cannot defer read-only value" { error require "defer" require "value" require "read-only" } unittest test { Int value <- 1 $ReadOnly[value]$ value <- defer } testcase "cannot defer hidden value" { error require "defer" require "value" require "hidden" } unittest test { Int value <- 1 $Hidden[value]$ value <- defer } testcase "deferred initialized in if/elif/else" { success } unittest test { Int value <- defer if (1 == 2) { value <- 1 } elif (1 == 3) { value <- 2 } else { value <- 3 } \ value } testcase "deferred missed in if" { error require "value" require "initialized" } unittest test { Int value <- defer if (1 == 2) { } elif (1 == 3) { value <- 2 } else { value <- 3 } \ value } testcase "deferred missed in elif" { error require "value" require "initialized" } unittest test { Int value <- defer if (1 == 2) { value <- 1 } elif (1 == 3) { } else { value <- 3 } \ value } testcase "deferred missed in else" { error require "value" require "initialized" } unittest test { Int value <- defer if (1 == 2) { value <- 1 } elif (1 == 3) { value <- 2 } else { } \ value } testcase "deferred initialized before cleanup" { success } unittest test { Int value <- defer cleanup { \ value } in value <- 1 } testcase "deferred initialized in cleanup" { success } unittest test { Int value <- defer cleanup { value <- 1 } in \ empty \ value } testcase "deferred initialized in scoped" { success } unittest test { Int value <- defer scoped { value <- 1 } in \ value } testcase "deferred not allowed in top-level scoped" { error require "defer" require "scoped" } unittest test { scoped { } in Int value <- defer } testcase "deferred propagated from scoped statement" { compiles } unittest test { Int value <- defer scoped { } in if (true) { value <- 1 } else { value <- 2 } \ value } testcase "deferred missed before cleanup" { error require "cleanup" require "value" require "initialized" } unittest test { Int value <- defer cleanup { \ value } in { if (true) { return _ } else { value <- 1 } } } testcase "deferred not checked in condition that jumps" { failure require "success" } unittest test { Int value <- defer if (true) { fail("success") } else { value <- 1 } \ value } testcase "deferred in nested block does not propagate" { success } unittest test { Int value <- 1 if (true) { value <- defer } else { value <- defer } \ value }