packages feed

zeolite-lang-0.24.0.0: tests/function-calls.0rt

/* -----------------------------------------------------------------------------
Copyright 2020-2021,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 "call from union failed merge" {
  error
  require "\[Value1\|Value2\]"
  require "get"
  require "[Mm]ultiple"
}

unittest test {
  [Value1 | Value2] value <- Value1.create()
  \ value.get()
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from union ambiguous base" {
  error
  require "\[Value1\|Value2\]"
  require "get"
  require "explicit"
  require "Base"
}

unittest test {
  [Value1 | Value2] value <- Value1.create()
  \ value.get()
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
  @value get () -> (Int)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from union bad function name" {
  error
  require "\[Int\|String\]"
  require "asFloat"
}

unittest test {
  [Int | String] value <- 1
  \ value.asFloat()
}


testcase "call from union automatic merge" {
  success
}

unittest test {
  [Value1 | Value2] value <- Value1.create()
  \ Testing.checkEquals(value.get().formatted(), "1")
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Formatted>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from union automatic merge correct direction" {
  error
  require "Formatted.+Int"
  require "\+"
  exclude "\[Value1\|Value2\]"
  exclude "get"
}

unittest test {
  [Value1 | Value2] value <- Value1.create()
  \ value.get()+1
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<Formatted>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from union explicit conversion" {
  success
}

unittest test {
  [Value1 | Value2] value <- Value1.create()
  \ Testing.checkEquals(value?Base<Formatted>.get().formatted(), "1")
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from all fails" {
  error
  require "formatted"
  require "all"
}

unittest test {
  optional all value <- empty
  \ require(value).formatted()
}


testcase "call from intersect failed merge" {
  error
  require "\[Base<AsBool>&Base<Formatted>\]"
  require "get"
  require "[Mm]ultiple"
}

unittest test {
  [Base<AsBool> & Base<Formatted>] value <- Value1.create()
  \ value.get()
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from intersect bad function name" {
  error
  require "\[AsBool&Formatted\]"
  require "asFloat"
}

unittest test {
  [AsBool & Formatted] value <- 1
  \ value.asFloat()
}


testcase "call from intersect automatic merge" {
  success
}

unittest test {
  [Base<Int> & Base<Formatted>] value <- Value1.create()
  \ Testing.checkEquals(value.get(), 1)
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from intersect explicit conversion" {
  success
}

unittest test {
  [Base<AsBool> & Base<Formatted>] value <- Value1.create()
  \ Testing.checkEquals(value?Base<Formatted>.get().formatted(), "1")
}

@value interface Base<|#x> {
  get () -> (#x)
}

concrete Value1 {
  refines Base<Int>
  @type create () -> (Value1)
}

define Value1 {
  get () {
    return 1
  }

  create () {
    return Value1{ }
  }
}

concrete Value2 {
  refines Base<String>
  @type create () -> (Value2)
}

define Value2 {
  get () {
    return "message"
  }

  create () {
    return Value2{ }
  }
}


testcase "call from param type" {
  success
}

unittest test {
  \ Test.check<Value>()
}

@type interface Base {
  call () -> ()
}

concrete Value {
  defines Base
}

define Value {
  call () { }
}

concrete Test {
  @type check<#x>
    #x defines Base
  () -> ()
}

define Test {
  check () {
    \ #x.call()
  }
}


testcase "call from bad param type" {
  error
  require "call.+param #x"
}

@type interface Base {
  call () -> ()
}

define Test {
  @type check<#x>
  () -> ()
  check () {
    \ #x.call()
  }
}

concrete Test { }



testcase "call from param value" {
  success
}

unittest test {
  Value value <- Value.create()
  \ Test.check<Value>(value)
}

@value interface Base {
  call () -> ()
}

concrete Value {
  refines Base

  @type create () -> (Value)
}

define Value {
  call () { }

  create () {
    return Value{}
  }
}

concrete Test {
  @type check<#x>
    #x requires Base
  (#x) -> ()
}

define Test {
  check (value) {
    \ value.call()
  }
}


testcase "call from bad param value" {
  error
  require "call.+param #x"
}

@value interface Base {
  call () -> ()
}

define Test {
  @type check<#x>
  (#x) -> ()
  check (value) {
    \ value.call()
  }
}

concrete Test { }


testcase "convert arg" {
  success
}

unittest test {
  \ Test.convert(Value.create()).call()
}

@value interface Base {
  call () -> ()
}

concrete Value {
  refines Base

  @type create () -> (Value)
}

define Value {
  call () { }

  create () {
    return Value{}
  }
}

concrete Test {
  @type convert (Value) -> (Base)
}

define Test {
  convert (value) {
    return value
  }
}


testcase "bad convert arg" {
  error
  require "does not refine Value"
}

@value interface Base { }

concrete Value { }

define Value { }

define Test {
  @type convert (Base) -> (Value)
  convert (value) {
    return value
  }
}

concrete Test { }


testcase "bad instance in param" {
  error
  require "Test"
  require "define"
  require "Equals"
}

unittest test {
  \ Call.call<Value<Test>>()
}

concrete Value<#x> {
  #x defines Equals<#x>
}

define Value { }

concrete Call {
  @type call<#x> () -> ()
}

define Call {
  call () { }
}


testcase "overwrite arg" {
  error
  require "arg"
}

define Test {
  @type call (Int) -> ()
  call (arg) {
    arg <- 2
  }
}

concrete Test { }


testcase "self in @category function" {
  error
  require "self"
}

define Test {
  @category call () -> ()
  call () {
    Test value <- self
  }
}

concrete Test { }


testcase "large dispatch tables" {
  success
}

unittest callDispatch {
  \ Testing.checkEquals(Type.new().get(), 00)
  \ Testing.checkEquals(Type.new().get01(), 01)
  \ Testing.checkEquals(Type.new().get02(), 02)
  \ Testing.checkEquals(Type.new().get03(), 03)
  \ Testing.checkEquals(Type.new().get04(), 04)
  \ Testing.checkEquals(Type.new().get05(), 05)
  \ Testing.checkEquals(Type.new().get06(), 06)
  \ Testing.checkEquals(Type.new().get07(), 07)
  \ Testing.checkEquals(Type.new().get08(), 08)
  \ Testing.checkEquals(Type.new().get09(), 09)
  \ Testing.checkEquals(Type.new().get10(), 10)
  \ Testing.checkEquals(Type.new().get11(), 11)
  \ Testing.checkEquals(Type.new().get12(), 12)
  \ Testing.checkEquals(Type.new().get13(), 13)
  \ Testing.checkEquals(Type.new().get14(), 14)
  \ Testing.checkEquals(Type.new().get15(), 15)
  \ Testing.checkEquals(Type.new().get16(), 16)
  \ Testing.checkEquals(Type.new().get17(), 17)
  \ Testing.checkEquals(Type.new().get18(), 18)
}

unittest reduceBuiltin {
  \ Testing.checkPresent(reduce<Type, Type>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base01>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base02>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base03>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base04>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base05>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base06>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base07>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base08>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base09>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base10>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base11>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base12>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base13>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base14>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base15>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base16>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base17>(Type.new()))
  \ Testing.checkPresent(reduce<Type, Base18>(Type.new()))
}

concrete Type {
  refines Base01
  refines Base02
  refines Base03
  refines Base04
  refines Base05
  refines Base06
  refines Base07
  refines Base08
  refines Base09
  refines Base10
  refines Base11
  refines Base12
  refines Base13
  refines Base14
  refines Base15
  refines Base16
  refines Base17
  refines Base18

  @type new () -> (Type)
  @value get () -> (Int)
}

define Type {
  new () { return Type{ } }
  get () { return 00 }
  get01 () { return 01 }
  get02 () { return 02 }
  get03 () { return 03 }
  get04 () { return 04 }
  get05 () { return 05 }
  get06 () { return 06 }
  get07 () { return 07 }
  get08 () { return 08 }
  get09 () { return 09 }
  get10 () { return 10 }
  get11 () { return 11 }
  get12 () { return 12 }
  get13 () { return 13 }
  get14 () { return 14 }
  get15 () { return 15 }
  get16 () { return 16 }
  get17 () { return 17 }
  get18 () { return 18 }
}

@value interface Base01 { get01 () -> (Int) }
@value interface Base02 { get02 () -> (Int) }
@value interface Base03 { get03 () -> (Int) }
@value interface Base04 { get04 () -> (Int) }
@value interface Base05 { get05 () -> (Int) }
@value interface Base06 { get06 () -> (Int) }
@value interface Base07 { get07 () -> (Int) }
@value interface Base08 { get08 () -> (Int) }
@value interface Base09 { get09 () -> (Int) }
@value interface Base10 { get10 () -> (Int) }
@value interface Base11 { get11 () -> (Int) }
@value interface Base12 { get12 () -> (Int) }
@value interface Base13 { get13 () -> (Int) }
@value interface Base14 { get14 () -> (Int) }
@value interface Base15 { get15 () -> (Int) }
@value interface Base16 { get16 () -> (Int) }
@value interface Base17 { get17 () -> (Int) }
@value interface Base18 { get18 () -> (Int) }


testcase "multiple mergeable @value functions match from filters" {
  compiles
}

@value interface Type1 {
  execute (Int) -> ()
}

@value interface Type2 {
  execute (Formatted) -> ()
}

concrete Test { }

define Test {
  @type test<#x>
    #x requires Type1
    #x requires Type2
  (#x) -> ()
  test (x) {
    \ x.execute("message")
  }
}


testcase "multiple mergeable @type functions match from filters" {
  compiles
}

@type interface Type1 {
  execute (Int) -> ()
}

@type interface Type2 {
  execute (Formatted) -> ()
}

concrete Test { }

define Test {
  @type test<#x>
    #x defines Type1
    #x defines Type2
  () -> ()
  test () {
    \ #x.execute("message")
  }
}


testcase "multiple unmergeable @value functions match from filters" {
  error
  require "[Mm]ultiple"
  require "execute"
}

@value interface Type1 {
  execute () -> (Int)
}

@value interface Type2 {
  execute () -> (String)
}

concrete Test { }

define Test {
  @type test<#x>
    #x requires Type1
    #x requires Type2
  (#x) -> ()
  test (x) {
    \ x.execute()
  }
}


testcase "multiple unmergeable @type functions match from filters" {
  error
  require "[Mm]ultiple"
  require "execute"
}

@type interface Type1 {
  execute () -> (Int)
}

@type interface Type2 {
  execute () -> (String)
}

concrete Test { }

define Test {
  @type test<#x>
    #x defines Type1
    #x defines Type2
  () -> ()
  test () {
    \ #x.execute()
  }
}


testcase "discarded args are skipped over" {
  success
}

unittest test {
  \ Testing.checkEquals(Value.create().call(1, "mess", 2, "age"), "message")
}

concrete Value {
  @type create () -> (Value)
  @value call (Int, String, any, Formatted) -> (String)
}

define Value {
  create () {
    return Value{}
  }

  call (_, x, _, y) {
    return x+y.formatted()
  }
}


testcase "@type function calls" {
  success
}

unittest sameType {
  \ Testing.checkEquals(Value<Int>.sameType(), "Value<Int>")
}

unittest sameValue {
  \ Testing.checkEquals(Value<Int>.create().sameValue(), "Value<Int>")
}

unittest diffType {
  \ Testing.checkEquals(Value<Int>.diffType<String>(), "Value<String>")
}

unittest diffValue {
  \ Testing.checkEquals(Value<Int>.create().diffValue<String>(), "Value<String>")
}

concrete Value<#x> {
  @type create () -> (#self)
  @type call () -> (String)
  @type  sameType      () -> (String)
  @value sameValue     () -> (String)
  @type  diffType<#y>  () -> (String)
  @value diffValue<#y> () -> (String)
}

define Value {
  create () {
    return #self{ }
  }

  call () {
    return typename<#self>().formatted()
  }

  sameType () {
    return Value<#x>.call()
  }

  sameValue () {
    return Value<#x>.call()
  }

  diffType () {
    return Value<#y>.call()
  }

  diffValue () {
    return Value<#y>.call()
  }
}


testcase "cannot use @category function as @type function" {
  error
  require "something"
  require "category"
}

concrete Test { }

define Test {
  @category something () -> ()
  something () { }

  @category test () -> ()
  test () {
    \ Test.something()
  }
}


testcase "cannot use @category function as @value function" {
  error
  require "something"
  require "category"
}

concrete Test { }

define Test {
  @category something () -> ()
  something () { }

  @category test () -> ()
  test () {
    \ Test{ }.something()
  }
}


testcase "cannot use @type function as @value function" {
  error
  require "something"
  require "value"
}

concrete Test { }

define Test {
  @type something () -> ()
  something () { }

  @category test () -> ()
  test () {
    \ Test{ }.something()
  }
}


testcase "cannot use @value function as @type function" {
  error
  require "something"
  require "type"
}

concrete Test { }

define Test {
  @value something () -> ()
  something () { }

  @category test () -> ()
  test () {
    \ Test.something()
  }
}


testcase "cannot implicitly use @value function as @type function" {
  error
  require "something"
}

concrete Test { }

define Test {
  @value something () -> ()
  something () { }

  @type test () -> ()
  test () {
    \ something()
  }
}