packages feed

zeolite-lang-0.24.0.0: tests/swap.0rt

/* -----------------------------------------------------------------------------
Copyright 2022-2023 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 "successful swaps" {
  success
}

concrete Test {
  @type new () -> (#self)
  @value testUnboxedCategoryValue () -> ()
  @value testBoxedCategoryValue () -> ()
  @value testWeakCategoryValue () -> ()
  @value testCategorySame () -> ()
  @value testUnboxedValueSame () -> ()
  @value testBoxedValueSame () -> ()
  @value testUnboxedNamedReturn () -> ()
  @value testBoxedNamedReturn () -> ()
}

define Test {
  @category Int         unboxedCategory <- 123
  @category String      boxedCategory   <- "abc"
  @category weak String weakCategory    <- boxedCategory

  @value Int         unboxedValue
  @value String      boxedValue
  @value weak String weakValue

  new () {
    String value <- "def"
    return #self{ 456, value, value }
  }

  testUnboxedCategoryValue () {
    unboxedCategory <-> unboxedValue
    \ Testing.checkEquals(unboxedCategory, 456)
    \ Testing.checkEquals(unboxedValue, 123)
    unboxedValue <-> unboxedCategory
    \ Testing.checkEquals(unboxedCategory, 123)
    \ Testing.checkEquals(unboxedValue, 456)
  }

  testBoxedCategoryValue () {
    boxedCategory <-> boxedValue
    \ Testing.checkEquals(boxedCategory, "def")
    \ Testing.checkEquals(boxedValue, "abc")
    boxedValue <-> boxedCategory
    \ Testing.checkEquals(boxedCategory, "abc")
    \ Testing.checkEquals(boxedValue, "def")
  }

  testWeakCategoryValue () {
    weakCategory <-> weakValue
    \ Testing.checkEquals(`strong` weakCategory, "def")
    \ Testing.checkEquals(`strong` weakValue, "abc")
    weakValue <-> weakCategory
    \ Testing.checkEquals(`strong` weakCategory, "abc")
    \ Testing.checkEquals(`strong` weakValue, "def")
  }

  testCategorySame () {
    boxedCategory <-> boxedCategory
    \ Testing.checkEquals(boxedCategory, "abc")
  }

  testUnboxedValueSame () {
    unboxedValue <-> unboxedValue
    \ Testing.checkEquals(unboxedValue, 456)
  }

  testBoxedValueSame () {
    boxedValue <-> boxedValue
    \ Testing.checkEquals(boxedValue, "def")
  }

  testUnboxedNamedReturn () {
    \ Testing.checkEquals(callWithNamedUnboxed(), 456)
  }

  testBoxedNamedReturn () {
    \ Testing.checkEquals(callWithNamedBoxed(), "def")
  }

  @value callWithNamedUnboxed () -> (Int)
  callWithNamedUnboxed () (value1) {
    value1     <- 123
    Int value2 <- 456
    value1 <-> value2
    \ Testing.checkEquals(value1, 456)
    \ Testing.checkEquals(value2, 123)
  }

  @value callWithNamedBoxed () -> (String)
  callWithNamedBoxed () (value1) {
    value1        <- "abc"
    String value2 <- "def"
    value1 <-> value2
    \ Testing.checkEquals(value1, "def")
    \ Testing.checkEquals(value2, "abc")
  }
}

unittest testUnboxedCategoryValue {
  \ Test.new().testUnboxedCategoryValue()
}

unittest testBoxedCategoryValue {
  \ Test.new().testBoxedCategoryValue()
}

unittest testWeakCategoryValue {
  \ Test.new().testWeakCategoryValue()
}

unittest testCategorySame {
  \ Test.new().testCategorySame()
}

unittest testUnboxedValueSame {
  \ Test.new().testUnboxedValueSame()
}

unittest testBoxedValueSame {
  \ Test.new().testBoxedValueSame()
}

unittest testUnboxedNamedReturn {
  \ Test.new().testUnboxedNamedReturn()
}

unittest testBoxedNamedReturn {
  \ Test.new().testBoxedNamedReturn()
}

unittest testUnboxedLocal {
  Int value1 <- 123
  Int value2 <- 456
  value1 <-> value2
  \ Testing.checkEquals(value1, 456)
  \ Testing.checkEquals(value2, 123)
}

unittest testBoxedLocal {
  String value1 <- "abc"
  String value2 <- "def"
  value1 <-> value2
  \ Testing.checkEquals(value1, "def")
  \ Testing.checkEquals(value2, "abc")
}

unittest testOptionalLocal {
  optional String value1 <- "abc"
  optional String value2 <- "def"
  value1 <-> value2
  \ Testing.checkEquals(value1, "def")
  \ Testing.checkEquals(value2, "abc")
}

unittest testWeakLocal {
  optional String source1 <- "abc"
  optional String source2 <- "def"
  weak String value1 <- source1
  weak String value2 <- source2
  $Hidden[source1, source2]$
  value1 <-> value2
  \ Testing.checkEquals(`strong` value1, "def")
  \ Testing.checkEquals(`strong` value2, "abc")
}

unittest testUnboxedTopLevelScoped {
  Int value1 <- 123
  scoped {
    Int value2 <- 456
  } cleanup {
    \ Testing.checkEquals(value1, 456)
  } in value1 <-> value2
  \ Testing.checkEquals(value1, 456)
}

unittest testBoxedTopLevelScoped {
  String value1 <- "abc"
  weak String reference <- value1
  scoped {
    String value2 <- "def"
  } cleanup {
    \ Testing.checkEquals(value1, "def")
    \ Testing.checkEquals(value2, "abc")
    \ Testing.checkEquals(`strong` reference, "abc")
  } in value1 <-> value2
  \ Testing.checkEquals(value1, "def")
  // value2 is out of scope now.
  \ Testing.checkEmpty(`strong` reference)
}


testcase "swap works with parameters" {
  success
}

concrete Test<#x> {
  #x requires Formatted
  #x defines Equals<#x>

  @type new (#x) -> (#self)
  @value testSwap (#x) -> ()
}

define Test {
  @value #x value

  new (value) { return #self{ value } }

  testSwap (value2) {
    // value2 is read-only because it's an argument.
    #x temp <- value2
    value <-> temp
  \ Testing.checkEquals(value, value2)
  }
}

unittest testUnboxed {
  \ Test<Int>.new(123).testSwap(456)
}

unittest testBxed {
  \ Test<String>.new("abc").testSwap("def")
}


testcase "swap not allowed with incompatible types" {
  error
  require "Int"
  require "String"
}

unittest test {
  Int    value1 <- 123
  String value2 <- "abc"
  value1 <-> value2
}


testcase "swap not allowed with invalid left assignment" {
  error
  require "modifier"
}

unittest test {
  Int          value1 <- 123
  optional Int value2 <- empty
  value1 <-> value2
}


testcase "swap not allowed with invalid right assignment" {
  error
  require "modifier"
}

unittest test {
  optional Int value1 <- empty
  Int          value2 <- 456
  value1 <-> value2
}


testcase "swap not allowed with read-only left" {
  error
  require "value1"
  require "read-only"
  exclude "value2"
}

unittest test {
  Int value1 <- 1
  Int value2 <- 2
  $ReadOnly[value1]$
  value1 <-> value2
}


testcase "swap not allowed with read-only right" {
  error
  require "value2"
  require "read-only"
  exclude "value1"
}

unittest test {
  Int value1 <- 1
  Int value2 <- 2
  $ReadOnly[value2]$
  value1 <-> value2
}


testcase "swap not allowed with hidden left" {
  error
  require "value1"
  require "hidden"
  exclude "value2"
}

unittest test {
  Int value1 <- 1
  Int value2 <- 2
  $Hidden[value1]$
  value1 <-> value2
}


testcase "swap not allowed with hidden right" {
  error
  require "value2"
  require "hidden"
  exclude "value1"
}

unittest test {
  Int value1 <- 1
  Int value2 <- 2
  $Hidden[value2]$
  value1 <-> value2
}


testcase "swap not allowed with deferred left" {
  error
  require "value1"
  require "initialized"
  exclude "value2"
}

unittest test {
  Int value1 <- defer
  Int value2 <- 2
  value1 <-> value2
}


testcase "swap not allowed with deferred right" {
  error
  require "value2"
  require "initialized"
  exclude "value1"
}

unittest test {
  Int value1 <- 1
  Int value2 <- defer
  value1 <-> value2
}