packages feed

zeolite-lang-0.20.0.0: tests/defer.0rt

/* -----------------------------------------------------------------------------
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 "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 "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 "cannot defer @value member" {
  error
  require "defer"
  require "value"
  require "local"
}

concrete Type {}

define Type {
  @value Int value

  @value call () -> ()
  call () {
    value <- defer
  }
}


testcase "cannot defer @category member" {
  error
  require "defer"
  require "value"
  require "local"
}

concrete Type {}

define Type {
  @category Int value <- 1

  @value call () -> ()
  call () {
    value <- defer
  }
}


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 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" {
  crash
  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
}