6.65. kink/javahost/JAVA

Javaオブジェクト、値、クラス、メソッドを操作する方法を提供する。

JAVAモジュールは、ホストシステムとの、境界のはっきりした統合を提供する意図で設計されている。Kinkの世界とJavaの世界の間には、明確な境界がある。たとえば、JavaのメソッドをKinkの関数として直接呼び出すことはできない。その代わりに、 .call_method を通して呼び出さなければならない。

Java_obj.call_method('toString')

この設計にはいくつかの理由がある。

1) オブジェクトシステムと、実行の意味論の両方で、KinkとJavaは根本的に異なる。したがって、シームレスな統合を実現することは難しい。

2) 一般的に、規模の大きなアプリケーションは、異なるシステム間に境界がある方が簡潔に設計できる。

3) 明確な境界があることで、KinkはJavaと独立に改善できる。

型付け可能

ここでは、Javaのオブジェクト参照とJavaの型の間の二項関係、「型付け可能」を定義する。

オブジェクト参照RがクラスオブジェクトTで型付け可能であるとき、次の条件のうちひとつが成り立つ。

• Tが参照型を表すクラスオブジェクトで、かつRがその参照型のインスタンスである。

• Tが参照型を表すクラスオブジェクトで、かつRがnullである。

• RがBoolean, Character, Byte, Short, Integer, Long, Float, Doubleのいずれかのインスタンスであり、かつTが対応するプリミティブ型を表すクラスオブジェクトである。

以降では、クラスオブジェクトと、そのクラスオブジェクトが表す型を、区別せずに言及する。

6.65.1. java型

java値は、(objectReference, type)の対である。ここで、objectReferenceはJavaのオブジェクトの参照であり、typeはクラスオブジェクトである。

typeは、Javaのインスタンスメソッド、インスタンスフィールドを検索するために使われる。

不変条件

objectReferenceはtypeで型付け可能でなければならない。

6.65.1.1. J.type

typeメソッドは、Jのtype属性を戻す。

typeメソッドの結果は、java値(t, java.lang.Class)になる。ここでtは、Jのtype属性である。

:JAVA.require_from('kink/javahost/')

:Comparable_class <- JAVA.class('java.lang.Comparable')
:Type <- JAVA.string('foo').as(Comparable_class).type
stdout.print_line(Type.repr) # => (java "interface java.lang.Comparable" as java.lang.Class)

6.65.1.2. J.as(New_type)

asは、typeをNew_typeに変える。

asの結果は、(ref, nt)のjava値になる。ここで、refはJのobjectReferenceであり、ntはNew_typeのobjectReferenceである。

事前条件

New_typeはjava値(nt, *)でなければならない。ここで、ntはクラスオブジェクトであり、JのobjectReferenceはntで型付け可能でなければならない。

:JAVA.require_from('kink/javahost/')
:Integer_class <- JAVA.class('java.lang.Integer')

:Int <- JAVA.int(42)
stdout.print_line(Int.repr)                   # => (java "42" as int)
stdout.print_line(Int.as(Integer_class).repr) # => (java "42" as java.lang.Integer)

6.65.1.3. J.instance_of?(Klass)

instance_of?は、JのobjectReferenceがKlassのインスタンスであるかどうかを戻す。このチェックは、Java言語のinstanceof演算子と同値である。

事前条件

Klassはjava値(klass, *)でなければならない。ここでklassは、java.lang.Classのインスタンスでなければならない。

:JAVA.require_from('kink/javahost/')
:Integer_class <- JAVA.class('java.lang.Integer')
:String_class <- JAVA.class('java.lang.String')
:Object_class <- JAVA.class('java.lang.Object')

stdout.print_line(JAVA.string('foo').instance_of?(String_class).repr)   # => true
stdout.print_line(JAVA.string('foo').instance_of?(Object_class).repr)   # => true
stdout.print_line(JAVA.string('foo').instance_of?(Integer_class).repr)  # => false

stdout.print_line(JAVA.int(42).instance_of?(Integer_class).repr)  # => true
stdout.print_line(JAVA.int(42).instance_of?(Object_class).repr)   # => true
stdout.print_line(JAVA.int(42).instance_of?(JAVA.int_class).repr) # => false

6.65.1.4. J.eq_eq?(Another)

eq_eq?は、JとAnotherのobjectReference属性が、Java言語の == の意味で同一かどうかを戻す。

事前条件

Anotherはjava値でなければならない。

:JAVA.require_from('kink/javahost/')

# null is eq_eq? null, irrespective of their types
:Null_string <- JAVA.null.as(JAVA.class('java.lang.String'))
:Null_integer <- JAVA.null.as(JAVA.class('java.lang.Integer'))
stdout.print_line(Null_string.eq_eq?(Null_integer).repr)  # => true

:Object_class <- JAVA.class('java.lang.Object')
:Str <- JAVA.string('foobar')
:Str_as_obj <- Str.as(Object_class)

# object is eq_eq? itself, irrespective their types
stdout.print_line(Str.eq_eq?(Str_as_obj).repr)        # => true

# object is not eq_eq? another object
stdout.print_line(Str.eq_eq?(Object_class.new).repr)  # => false

6.65.1.5. J.null?

null?は、JのobjectReference属性がnullであるかどうかを戻す。

6.65.1.6. J.to_kink_str

to_kink_strは、Java文字列からstr値を作って戻す。

事前条件

JのobjectReferenceはjava.lang.Stringのインスタンスでなければならない。

:JAVA.require_from('kink/javahost/')

:Java_string <- JAVA.string('foobar')
:Kink_str <- Java_string.to_kink_str
stdout.print_line(Kink_str.repr)  # => "foobar"

6.65.1.7. J.to_kink_bool

to_kink_boolは、Javaのbooleanからbool値を作って戻す。

事前条件

JのobjectReferenceはjava.lang.Booleanのインスタンスでなければならない。

:JAVA.require_from('kink/javahost/')

:Empty <- JAVA.string('')
:Non_empty <- JAVA.string('foo')
stdout.print_line(Empty.call_method('isEmpty').to_kink_bool.repr)     # => true
stdout.print_line(Non_empty.call_method('isEmpty').to_kink_bool.repr) # => false

6.65.1.8. J.to_kink_num

to_kink_numは、Javaの数値からnum値を作って戻す。

Character, Byte, Short, Integer, Long, BigIntegerからの変換

JのobjectReferenceがCharacter, Byte, Short, Integer, Long, BigIntegerのいずれかの場合、結果のnumのScaleは0になる。また、結果のnumのMantissaは元の整数になる。

Float, Doubleからの変換

JのobjectReferenceがFloatかDoubleの場合、結果のnumのScaleは、数値が正確に表現できる最小の非負の整数になる。また、Mantissaは `J * (10 ^ Scale)` になる。

0の符号は結果に保存されない。

BigDecimalからの変換

JのobjectReferenceがBigDecimalの場合、結果のnumのScaleはBigDecimal.scale()の結果と等しくなり、MantissaはBigDecimal.unscaledValue()の結果と等しくなる。

事前条件

JのobjectReferenceは、Character, Byte, Short, Integer, Long, Float, Double, BigInteger, BigDecimalのいずれかのインスタンスでなければならない。

参照がFloatかDoubleのとき、それはNaNや正負の無限大であってはならない。

参照がBigIntegerのとき、それはnum値のサポートされているMantissaの範囲になければならない。

参照がBigDecimalのとき、そのスケールはnum値のサポートされているScaleの範囲にあり、またスケールされない値はnum値のサポートされているMantissaの範囲になければならない。

:JAVA.require_from('kink/javahost/')

:Ans <- JAVA.byte(42).to_kink_num
stdout.print_line(Ans.repr)           # => 42
stdout.print_line(Ans.scale.repr)     # => 0
stdout.print_line(Ans.mantissa.repr)  # => 42

:Pi <- JAVA.float(3.14).to_kink_num
stdout.print_line(Pi.repr)          # => 3.1400001049041748046875
stdout.print_line(Pi.scale.repr)    # => 22
stdout.print_line(Pi.mantissa.repr) # => 31400001049041748046875

6.65.1.9. J.to_kink_bin(...[From To])

to_kink_binは、Javaのバイト配列からbin値を作って戻す。

Fromのデフォルト値は0である。Toのデフォルト値はバイト配列の長さである。

結果のbinの長さは `To - From` になる。binは、Jの[From, To)の範囲のスライスのバイトを含む。

事前条件

Jはjava値(bytes, *)でなければならない。ここでbytesはbyte[]のインスタンスでなければならない。

FromとToは整数のnum値でなければならない。

0 <= From <= To <= bytes.length

:JAVA.require_from('kink/javahost/')

:Bytes <- JAVA.byte_class.array_of(
  JAVA.byte(0) JAVA.byte(1) JAVA.byte(2) JAVA.byte(3) JAVA.byte(4))
:Copy <- Bytes.to_kink_bin
stdout.print_line(Copy.repr) # => (bin 0x00 0x01 0x02 0x03 0x04)

:Slice <- Bytes.to_kink_bin(1 4)
stdout.print_line(Slice.repr) # => (bin 0x01 0x02 0x03)

6.65.1.10. J.to_kink_exception

to_kink_exceptionは、JavaのThrowableからexception値を作って戻す。

to_kink_exceptionはThrowable.toStringをMessageに、Throwable.getStackTraceをTracesに、Throwable.getCauseとgetSuppressedをNextに、それぞれexception値の属性としてエンコードする。

他のthrowableの属性、たとえばSQLException.getErrorCodeなどは保存されない。

事前条件

JのobjectReferenceはjava.lang.Throwableのインスタンスでなければならない。

:JAVA.require_from('kink/javahost/')

JAVA.big_integer(42).call_method('divide' JAVA.big_integer(0)){(:C)
  C.catch(JAVA.class('java.lang.ArithmeticException')){(:Java_exc)
    :Exc = Java_exc.to_kink_exception
    Exc.desc_iter.each{(:Str)
      stdout.print_line(Str)
    }
  }
}
# Output:
#   -- main exception
#   [org.kink_lang.kink/org.kink_lang.kink.internal.startup.Kink.main(Kink.java:34)]
#   [org.kink_lang.kink/org.kink_lang.kink.Vm.run(Vm.java:217)]
#   ,,,
#   [java.base/java.math.BigInteger.divideKnuth(BigInteger.java:2447)]
#   [java.base/java.math.MutableBigInteger.divideKnuth(MutableBigInteger.java:1184)]
#   java.lang.ArithmeticException: BigInteger divide by zero

6.65.1.11. J.unwrap

unwrapは、JAVA.wrapでラップされたKinkの値を抜き出す。

Jがjava値(Wrapped, ? super org.kink_lang.kink.Val)のとき、unwrapはWrappedを戻す。

事前条件

Jはjava値(Wrapped, *)でなければならない。ここで、Wrappedはorg.kink_lang.kink.Valのインスタンスで、かつWrappedのランタイムは現在のランタイムと同じでなければならない。

:JAVA.require_from('kink/javahost/')
:VAL.require_from('kink/')

:Str <- 'foo'
:Wrapped_str <- JAVA.wrap(Str)
stdout.print_line(Wrapped_str.repr)  # (java "StrVal(foo)" as org.kink_lang.kink.Val)

:Unwrapped_str <- Wrapped_str.unwrap
stdout.print_line(Unwrapped_str.repr) # => "foo"
stdout.print_line(VAL.same?(Unwrapped_str Str).repr) # => true

6.65.1.12. J.array_class

array_classは、与えられた要素型の配列クラスのクラスオブジェクトを戻す。

JのobjectReferenceがCのとき、array_classはjava値(C[], java.lang.Class)を戻す。

事前条件

Jはjava値(C, *)でなければならない。ここでCはクラスオブジェクトでなければならない。

Cはvoidであってはならない。

Cが配列クラスのとき、その次元は254を超えてはならない。

:JAVA.require_from('kink/javahost/')

:Array_class <- JAVA.int_class.array_class
stdout.print_line(Array_class.repr)  # => (java "class [I" as java.lang.Class)

6.65.1.13. J.array_new(Size)

array_newは、与えられた要素型とサイズの配列を戻す。

JのobjectReferenceがCのとき、array_newはjava値(Array, C[])を戻す。ここで、Arrayは長さがSizeの配列である。

Arrayの要素はCのゼロ値で初期化される。

事前条件

Jはjava値(C, *)でなければならない。ここでCはクラスオブジェクトでなければならない。

Cはvoidであってはならない。

Cが配列クラスのとき、その次元は254を超えてはならない。

Sizeは非負の整数のnum値でなければならない。

:JAVA.require_from('kink/javahost/')

:Array <- JAVA.int_class.array_new(2)
stdout.print_line(Array.repr)               # => (java "[I@4722ef0c" as [I)
stdout.print_line(Array.array_length.repr)  # => 2

6.65.1.14. J.array_of(...[E0 E1 ,,,])

array_ofは、与えられた要素を含む配列を戻す。

JのobjectReferenceがCのとき、array_ofはjava値(Array, C[])を戻す。ここで、ArrayはE0, E1, ,,, を要素として持つ配列である。

事前条件

Jはjava値(C, *)でなければならない。ここでCはクラスオブジェクトでなければならない。

Cはvoidであってはならない。

Cが配列クラスのとき、その次元は254を超えてはならない。

E0, E1, ,,, はjava値であり、そのobjectReference属性は、JのobjectReferenceで型付け可能でなければならない。

:JAVA.require_from('kink/javahost/')

:Array <- JAVA.int_class.array_of(JAVA.int(10) JAVA.int(20))
stdout.print_line(Array.repr)               # => (java "[I@4722ef0c" as [I)
stdout.print_line(Array.array_get(0).repr)  # => (java "10" as int)
stdout.print_line(Array.array_get(1).repr)  # => (java "20" as int)
stdout.print_line(Array.array_length.repr)  # => 2

6.65.1.15. J.array_length

array_lengthは、配列の長さを整数のnum値として戻す。

事前条件

Jはjava値(array, *)でなければならない。ここでarrayは配列でなければならない。

6.65.1.16. J.array_get(Ind)

array_getは、配列Jの添字Indにおける要素を戻す。

配列の要素型が参照型rtのとき、array_getは、java値(element, rt)を戻す。ここでelementは配列の要素である。

配列の要素型がプリミティブ型ptのとき、array_getはjava値(box, pt)を戻す。ここでboxは、対応するラッパ型のインスタンスであり、その中身として配列の要素を持つ。

事前条件

Jはjava値(array, *)でなければならない。ここでarrayは配列でなければならない。

Indは、[0, length)の範囲の整数のnumでなければならない。ここでlengthは配列の長さである。

6.65.1.17. J.array_set(Ind Elem)

array_setは、値Elemを配列Jの添字Indの場所に書き込む。

事前条件

Jはjava値(array, *)でなければならない。ここでarrayは配列でなければならない。

Indは、[0, length)の範囲の整数のnumでなければならない。ここでlengthは配列の長さである。

Elemはjava値(elem, *)でなければならない。ここでelemは配列の要素型で型付け可能でなければならない。

6.65.1.18. J.get_field(Field_name)

get_fieldは、publicなインスタンスフィールドの内容を戻す。

フィールドは、Jのtypeから、Class.getField(String)を使って検索される。

フィールドの宣言型が参照型rtのとき、結果はjava値(contentObj, rt)になる。ここでcontentObjはフィールドの内容である。

フィールドの宣言型がプリミティブ型ptのとき、結果はjava値(box, pt)になる。ここでboxは、対応するラッパ型のインスタンスであり、その中身としてフィールドの内容を持つ。

事前条件

Jはjava値でなければならない。

Field_nameはstrでなければならない。

Jのtypeは、Field_nameの名前の、publicなインスタンスフィールドを持っていなければならない。

:JAVA.require_from('kink/javahost/')

:True <- JAVA.runtime.get_field('bool').get_field('trueVal')
stdout.print_line(True.repr) # => (java "trueVal" as org.kink_lang.kink.Val)

6.65.1.19. J.set_field(Field_name Content)

set_fieldは、Contentをpublicなインスタンスフィールドに書き込む。

フィールドは、Jのtypeから、Class.getField(String)を使って検索される。

事前条件

Jはjava値でなければならない。

Field_nameはstrでなければならない。

Jのtypeは、Field_nameの名前の、publicなインスタンスフィールドを持っていなければならない。

フィールドはfinalであってはならない。

Contentはjava値(contentObj, *)でなければならない。ここでcontentObjは、フィールドの宣言型で型付け可能でなければならない。

6.65.1.20. J.get_static(Field_name)

get_staticは、クラスJのpublic staticフィールドの内容を戻す。

JのobjectReferenceがクラスオブジェクトownerClassのとき、フィールドはownerClassから、Class.getField(String)を使って検索される。

フィールドの宣言型が参照型rtのとき、結果はjava値(contentObj, rt)になる。ここでcontentObjはフィールドの内容である。

フィールドの宣言型がプリミティブ型ptのとき、結果はjava値(box, pt)になる。ここでboxは、対応するラッパ型のインスタンスであり、その中身としてフィールドの内容を持つ。

事前条件

Jはjava値(ownerClass, *)でなければならない。ここで、ownerClassはjava.lang.Classのインスタンスでなければならない。

Field_nameはstrでなければならない。

ownerClassは、Field_nameの名前を持つpublic staticフィールドを持っていなければならない。

:JAVA.require_from('kink/javahost/')

:Byte_class <- JAVA.class('java.lang.Byte')
:Byte_max <- Byte_class.get_static('MAX_VALUE')
stdout.print_line(Byte_max.repr)  # => (java "127" as byte)

6.65.1.21. J.set_static(Field_name Content)

set_staticは、クラスJのpublic staticフィールドにContentを書き込む。

JのobjectReferenceがクラスオブジェクトownerClassのとき、フィールドはownerClassから、Class.getField(String)を使って検索される。

事前条件

Jはjava値(ownerClass, *)でなければならない。ここで、ownerClassはjava.lang.Classのインスタンスでなければならない。

Field_nameはstrでなければならない。

ownerClassは、Field_nameの名前を持つpublic staticフィールドを持っていなければならない。

フィールドはfinalであってはならない。

Contentはjava値(contentObj, *)でなければならない。ここでcontentObjは、フィールドの宣言型で型付け可能でなければならない。

6.65.1.22. J.call_method(Method_name ...[A0 A1 ,,,] ...[$config={}])

call_methodは、オブジェクトJのpublicなインスタンスメソッドを呼び出す。

検索

インスタンスメソッドは `J.type.getMethod(Method_name, A0.type, A1.type, ,,,)` で検索される。

結果

1) メソッドの宣言された戻り型が参照型rtで、メソッドが例外を投げずに終わったとき、call_methodは、java値(resultObj, rt)を引数として成功時継続を末尾呼び出しする。ここでresultObjはメソッドの戻り値である。

2) メソッドの宣言された戻り型ptがchar, boolean, byte, short, int, long, float, doubleのいずれかで、メソッドが例外を投げずに終わったとき、call_methodは、java値(resultObj, pt)を引数として成功時継続を末尾呼び出しする。ここでresultObjは戻り値のラッパインスタンスである。

3) メソッドの宣言された戻り型がvoidで、メソッドが例外を投げずに終わったとき、call_methodは、引数なしで成功時継続を末尾呼び出しする。

4) メソッドがJavaの例外exceptionObjを投げて終わり、その例外がC.catchの呼び出しで指定されたひとつ以上の例外型のインスタンスであるとき、call_methodは、最も狭い型etに対応するエラー時継続を、java値(exceptionObj, et)を引数として末尾呼び出しする。

5) メソッドがJavaの例外を投げて終わり、C.catchに渡された例外型のどれもが投げられた例外に合致しなかったとき、call_methodはKinkの例外を投げる。

コンフィグ値のC.on_successが呼ばれず、メソッドの宣言された戻り型がvoidのときは、{ nada }がデフォルトの成功時継続として使われる。

コンフィグ値のC.on_successが呼ばれず、メソッドの宣言された戻り型がvoidでないときは、VAL.identityがデフォルトの成功時継続として使われる。

事前条件

Method_nameはstrでなければならない。

A0, A1 ,,, はjava値でなければならない。

Jのtypeは、指定されたpublicインスタンスメソッドを持っていなければならない。

$configは、java_call_config値を取る関数でなければならない。

:JAVA.require_from('kink/javahost/')
:ArrayList_class <- JAVA.class('java.util.ArrayList')
:Object_class <- JAVA.class('java.lang.Object')
:Lst <- ArrayList_class.new

# .as(Object_class) is required,
# because the method is looked up using static types of the args
Lst.call_method('add' JAVA.string('foo').as(Object_class))
Lst.call_method('add' JAVA.int(42).as(Object_class))

stdout.print_line(Lst.repr) # => (java "[foo, 42]" as java.util.ArrayList)

# call ArrayList.remove(int)
:Removed <- Lst.call_method('remove' JAVA.int(0))
stdout.print_line(Removed.repr) # => (java "foo" as java.lang.Object)

# call ArrayList.remove(java.lang.Object)
:Success <- Lst.call_method('remove' JAVA.int(42).as(Object_class))
stdout.print_line(Success.repr) # => (java "true" as boolean)

デフォルトでは、Javaの例外はKinkの例外として投げられる。

:CONTROL.require_from('kink/')
:JAVA.require_from('kink/javahost/')
:ArrayList_class <- JAVA.class('java.util.ArrayList')
:Lst <- ArrayList_class.new

CONTROL.try(
  { Lst.call_method('get' JAVA.int(42)) }
  {(:R) raise('must not reach here') }
  {(:Exc)
    stdout.print_line(Exc.message)
  }
)
# => java exception: java.lang.IndexOutOfBoundsException: Index 42 out of bounds for length 0

成功、エラーの継続は、コンフィグ関数で設定できる。

:JAVA.require_from('kink/javahost/')
:BigInteger_class <- JAVA.class('java.math.BigInteger')

:divide_10_by <- {(:Divisor)
  BigInteger_class.get_static('TEN').call_method('divide' Divisor){(:C)
    C.on_success{(:R)
      'result: {}'.format(R.repr)
    }
    C.catch(JAVA.class('java.lang.RuntimeException')){(:Exc)
      'rte: {}'.format(Exc.repr)
    }
    C.catch(JAVA.class('java.lang.Exception')){(:Exc)
      'exception: {}'.format(Exc.repr)
    }
  }
}

stdout.print_line(divide_10_by(JAVA.big_integer(2)))
# => result: (java "5" as java.math.BigInteger)

stdout.print_line(divide_10_by(JAVA.big_integer(0)))
# => rte: (java "java.lang.ArithmeticException: BigInteger divide by zero" as java.lang.RuntimeException)

Javaメソッドの戻り型がvoidのとき、成功時継続は引数なしで末尾呼び出しされる。

:JAVA.require_from('kink/javahost/')
:ArrayList_class <- JAVA.class('java.util.ArrayList')
:Object_class <- JAVA.class('java.lang.Object')

:Lst <- ArrayList_class.new
Lst.call_method('add' JAVA.string('foo').as(Object_class))
Lst.call_method('add' JAVA.string('bar').as(Object_class))

Lst.call_method('clear'){(:C)
  C.on_success{()
    stdout.print_line('cleared!')
  }
}
# => cleared!

6.65.1.23. J.call_static(Method_name ...[A0 A1 ,,,] ...[$config={}])

call_staticは、クラスJのpublicなstaticメソッドを呼び出す。

検索

JのobjectReferenceがownerClassのとき、staticメソッドは `ownerClass.getMethod(Method_name, A0.type, A1.type, ,,,)` で検索される。

結果

J.call_methodと同じ。

事前条件

Jはjava値(ownerClass, *)でなければならない。ここでownerClassはクラスオブジェクトでなければならない。

Method_nameはstrでなければならない。

A0, A1 ,,, はjava値でなければならない。

ownerClassは指定されたpublicなstaticメソッドを持っていなければならない。

$configは、java_call_config値を取る関数でなければならない。

:JAVA.require_from('kink/javahost/')

:String_class <- JAVA.class('java.lang.String')
:Object_class <- JAVA.class('java.lang.Object')
:Java_str <- String_class.call_static(
  'format' JAVA.string('ans=%d') Object_class.array_of(JAVA.int(42)))
stdout.print_line(Java_str.repr)  # => (java "ans=42" as java.lang.String)

6.65.1.24. J.new(...[A0 A1 ,,,] ...[$config={}])

newは、Jのpublicなコンストラクタを呼んで、新しいインスタンスを戻す。

検索

JのobjectReferenceがクラスオブジェクトownerClassのとき、publicコンストラクタは、 `ownerClass.getConstructor(A0.type, A1.type, ,,,)` で検索される。

結果

1) 新しいインスタンスresultObjが作られたとき、newは、java値(resultObj, ownerClass)を引数として成功時継続を末尾呼び出しする。

2) コンストラクタがJavaの例外exceptionObjを投げて終わり、その例外がC.catchの呼び出しで指定されたひとつ以上の例外型のインスタンスであるとき、newは、最も狭い型etに対応するエラー時継続を、java値(exceptionObj, et)を引数として末尾呼び出しする。

3) コンストラクタがJavaの例外を投げて終わり、C.catchに渡された例外型のどれもが投げられた例外に合致しなかったとき、newはKinkの例外を投げる。

コンフィグ値のC.on_successが呼ばれないときは、VAL.identityがデフォルトの成功時継続として使われる。

事前条件

Jはjava値(ownerClass, *)でなければならない。ここでownerClassはクラスオブジェクトでなければならない。

A0, A1 ,,, はjava値でなければならない。

ownerClassは指定されたpublicなコンストラクタを持っていなければならない。

$configは、java_call_config値を取る関数でなければならない。

:CONTROL.require_from('kink/')
:JAVA.require_from('kink/javahost/')
:BigDecimal_class <- JAVA.class('java.math.BigDecimal')

:make_big_decimal <- {(:Str)
  BigDecimal_class.new(JAVA.string(Str))
}

stdout.print_line(make_big_decimal('12.3').repr)  # => (java "12.3" as java.math.BigDecimal)

CONTROL.try(
  { make_big_decimal('xxx') }
  {(:R) raise('must not reach here') }
  {(:Exc)
    stdout.print_line(Exc.message)
  }
)
# => java exception: java.lang.NumberFormatException: Character x is neither a decimal digit number, decimal point, nor "e" notation exponential mark.

6.65.2. java_call_config型

java_call_configは、J.call_method, J.call_static, J.newのコンフィグ値である。

6.65.2.1. C.on_success($success)

on_successは、$successを成功時継続として指定する。

6.65.2.2. C.catch(Exception_class $error)

catchは、例外型Exception_classに対応するエラー時継続として$errorを指定する。

catchは、異なる例外型に対応するエラー時継続を指定するために、複数回呼び出せる。

事前条件

Exception_classはjava値(et, *)でなければならない。ここでetは、java.lang.Throwableのサブクラスでなければならない。

Exception_classは、先行するcatchの呼び出しで指定された例外型の部分型であってはならない。

$errorはjava値を取る関数でなければならない。

6.65.3. JAVA.is?(Val)

is?は、Valがjava値であるかどうかを戻す。

6.65.4. JAVA.string(Str)

stringは、Strと同じ文字列を持つJava文字列を戻す。

結果はjava値(string, java.lang.String)になる。ここでstringはStringのインスタンスであり、Strと同じ文字列を持つ。

事前条件

Strはstr値でなければならない。

6.65.5. JAVA.bytes(Bin ...[From=0 To=Bin.size])

bytesは、Binの範囲[From, To)のスライスからJavaのバイト配列を作って戻す。

結果はjava値(byteArray, byte[])になる。ここでbyteArrayはbyte配列であり、その要素はBinの範囲[From, To)のスライスからコピーされる。

事前条件

Binはbin値でなければならない。

FromとToは整数のnum値でなければならない。

0 <= From <= To <= Bin.size

6.65.6. JAVA.byte_buffer(Bin)

byte_bufferは、Binのバイト列を持つ読み込み専用のByteBufferを戻す。

結果はjava値(byteBuffer, java.nio.ByteBuffer)になる。ここでbyteBufferは次の属性を持つ。

• capacityと、limitの初期値はBin.sizeになる。

• positionお初期値は0になる。

事前条件

Binはbin値でなければならない。

6.65.7. JAVA.boolean(Bool)

booleanは、Boolに対応するJavaのboolean値を戻す。

Boolがtrueのとき、booleanはjava値(Boolean.TRUE, boolean)を戻す。

Boolがfalseのとき、booleanはjava値(Boolean.FALSE, boolean)を戻す。

事前条件

Boolはbool値でなければならない。

6.65.8. JAVA.char(Num)

charはNumに対応するJavaのchar値を戻す。

結果は(objectReference=ch, type=char)というjava値になる。chはjava.lang.Characterのインスタンスである。

事前条件

Numは[0, 0xffff]の範囲内の整数のnum値でなければならない。

6.65.9. JAVA.byte(Num)

byteはNumに対応するJavaのbyte値を戻す。

結果は(objectReference=bt, type=byte)というjava値になる。btはjava.lang.Byteのインスタンスである。

事前条件

Numは[-128, 127]の範囲内の整数のnum値でなければならない。

6.65.10. JAVA.short(Num)

shortはNumに対応するJavaのshort値を戻す。

結果は(objectReference=sh, type=short)というjava値になる。shはjava.lang.Shortのインスタンスである。

事前条件

Numは[- 2**15, 2**15 - 1]の範囲内の整数のnum値でなければならない。

6.65.11. JAVA.int(Num)

intはNumに対応するJavaのint値を戻す。

結果は(objectReference=n, type=int)というjava値になる。nはjava.lang.Integerのインスタンスである。

事前条件

Numは[- 2**31, 2**31 - 1]の範囲内の整数のnum値でなければならない。

6.65.12. JAVA.long(Num)

longはNumに対応するJavaのlong値を戻す。

結果は(objectReference=ln, type=long)というjava値になる。lnはjava.lang.Longのインスタンスである。

事前条件

Numは[- 2**63, 2**63 - 1]の範囲内の整数のnum値でなければならない。

6.65.13. JAVA.float(Num)

floatは、数値的にNumに近いJavaのfloat値を戻す。

結果はjava値(fl, float)になる。ここでflは、java.lang.Floatのインスタンスであり、その値はBigDecimal.floatValue()でNumから変換されたものである。

事前条件

Numはnum値でなければならない。

6.65.14. JAVA.double(Num)

doubleは、数値的にNumに近いJavaのdouble値を戻す。

結果はjava値(dbl, double)になる。ここでdblは、java.lang.Doubleのインスタンスであり、その値はBigDecimal.doubleValue()でNumから変換されたものである。

事前条件

Numはnum値でなければならない。

6.65.15. JAVA.big_integer(Num)

big_integerはNumに対応するJavaのBigInteger値を戻す。

結果はjava値(objectReference=bi, staticType=java.math.BigInteger)になる。biはjava.math.BigIntegerのインスタンスであり、その値はNumに等しい。

事前条件

Numは整数のnum値でなければならない。

6.65.16. JAVA.big_decimal(Num)

big_decimalは、Numに対応するJavaのBigDecimalを戻す。

結果はjava値(bd, java.math.BigDecimal)になる。ここでbdは、java.math.BigDecimalのインスタンスであり、そのscaleはNumのScaleに等しく、unscaledValueはNumのMantissaに等しい。

事前条件

Numはnum値でなければならない。

6.65.17. JAVA.wrap(Wrapped)

wrapは、Kinkの値をラップするjava値を戻す。

Wrappedはどんな型の値でも良い。wrapは、(Wrapped, org.kink_lang.kink.Val)のjava値を戻す。

Wrappedは、結果のjava値から、unwrapメソッドで抜き出せる。

:JAVA.require_from('kink/javahost/')

:Str <- 'foo'
:Wrapper <- JAVA.wrap(Str)
stdout.print_line(Wrapper.repr)   # (java "StrVal(foo)" as org.kink_lang.kink.Val)
stdout.print_line(Wrapper.unwrap.repr)  # => "foo"

6.65.18. JAVA.true

trueは、java値(Boolean.TRUE, boolean)を戻す。

6.65.19. JAVA.false

falseは、java値(Boolean.FALSE, boolean)を戻す。

6.65.20. JAVA.null

nullは、java値(null, java.lang.Object)を戻す。

6.65.21. JAVA.runtime

runtimeは現在のランタイムを戻す。

結果はjava値(vm, org.kink_lang.kink.Vm)である。ここでvmは現在のランタイムである。

6.65.22. JAVA.boolean_class

boolean_classは、java値(boolean.class, java.lang.Class)を戻す。

6.65.23. JAVA.char_class

char_classは、java値(char.class, java.lang.Clsas)を戻す。

6.65.24. JAVA.byte_class

byte_classは、java値(byte.class, java.lang.Class)を戻す。

6.65.25. JAVA.short_class

short_classは、java値(short.class, java.lang.Class)を戻す。

6.65.26. JAVA.int_class

int_classは、java値(int.class, java.lang.Class)を戻す。

6.65.27. JAVA.long_class

long_classは、java値(long.class, java.lang.Class)を戻す。

6.65.28. JAVA.float_class

float_classは、java値(float.class, java.lang.Class)を戻す。

6.65.29. JAVA.double_class

double_classは、java値(double.class, java.lang.Class)を戻す。

6.65.30. JAVA.void_class

void_classは、java値(void.class, java.lang.Class)を戻す。

6.65.31. JAVA.class(Class_name ...[$config={}])

classは、バイナリ名Class_nameでクラスを検索する。

コンフィグメソッド:

• C.on_success($success): default = VAL.identity

• C.on_error($error): default = 例外を投げる関数

classは、指定されたクラスをロードするのに、現在のランタイムのorg.kink_lang.kink.Vmクラスがロードされたクラスローダの、無名モジュールのリフレクションアクセスを使う。

クラスklassが見つかったとき、classは、java値(klass, java.lang.Class)を引数として$successを末尾呼び出しする。

クラスが見つからないとき、classは$errorを引数なしで末尾呼び出しする。

事前条件

Class_nameはstr値でなければならない。

$successはjava値を取る関数でなければならない。

$errorはサンクでなければならない。