TESTS: added tests for issue #237 & #238 to namespace tests

Red/System [
	Title:   "Red/System null test script"
	Author:  "Nenad Rakocevic & Peter W A Wood"
	File: 	 %namespace-test.reds
	Rights:  "Copyright (C) 2011 Nenad Rakocevic & Peter W A Wood. All rights reserved."
	License: "BSD-3 - https://github.com/dockimbel/Red/blob/origin/BSD-3-License.txt"
]

#include %../../../../quick-test/quick-test.reds

~~~start-file~~~ "namespace"

    nmsp1: context [
      i: 123
      f: 1.23
      f32: as float32! 2.46
      l: true
      s: "my string"
      fn: func [pi [pointer! [integer!]] return: [integer!]] [pi/value: 789 789]
      fn2: func [
        i [integer!]
        return: [integer!]
      ][ 2 * i]
      st: declare struct! [
        a [integer!]
        b [integer!]
      ]
    ]

    i: 987
	ctx: context [
		i: 123
		j: "test"
		foo: func [return: [integer!]][
			i: i + 1
			i
		]
		--test-- "in-ns1"
		--assert 124 = foo
	]

===start-group=== "basic"

  --test-- "ns1"
  --assert 123 = nmsp1/i
  --test-- "ns2"
  --assert 1.23 = nmsp1/f
  --test-- "ns3"
  --assert (as float32! 2.46) = nmsp1/f32
  --test-- "ns4"
  --assert nmsp1/l
  --test-- "ns5"
  --assert nmsp1/s/1 = #"m"
  --assert nmsp1/s/2 = #"y"
  --assert nmsp1/s/3 = #" "
  --assert nmsp1/s/4 = #"s"
  --assert nmsp1/s/5 = #"t"
  --assert nmsp1/s/6 = #"r"
  --assert nmsp1/s/7 = #"i"
  --assert nmsp1/s/8 = #"n"
  --assert nmsp1/s/9 = #"g"
  --test-- "ns6"
    nmsp1/s: "hello"
  --assert 5 = length? nmsp1/s
  --test-- "ns7"
    ns1-b-i: 0
  --assert 789 = nmsp1/fn :ns1-b-i
  --test-- "ns8"
    ns1-b-i: 4
  --assert 8 = nmsp1/fn2 ns1-b-i
  --test-- "ns9"
    nmsp1/st/a: 1
  --assert nmsp1/st/a = 1
  --test-- "ns10"
  --assert ctx/j/1 = #"t"
  --test-- "ns11"
  --assert ctx/foo = 125
  --test-- "ns12"
    ctx/i: ctx/i + 1
  --assert ctx/i = 126
  --assert i = 987
  --test-- "ns13"
    ns13i: 1
    ns13i-nsp: context [
      ns13i: 2
      get-ns13i: func [return: [integer!]] [ns13i]
    ]
  --assert 2 = ns13i-nsp/get-ns13i

===end-group===

===start-group=== "hiding"
    i: 321
    f: 3.21
    f32: as float32! 6.42
    l: false
    s: "not my string"
    fn: func [pi [pointer! [integer!]]] [pi/value: 987]
    fn2: func[
        i [integer!]
        return: [integer!]
      ][ 3 * i]
    st: declare struct! [
        a [integer!]
        b [integer!]
    ]

  --test-- "nmh1"
    nmsp1/i: 789
  --assert i = 321
  --test-- "nmh2"
    nmsp1/f: 7.89
  --assert f = 3.21
  --test-- "nmh3"
    nmsp1/f32: as float32! 7.89
  --assert nmsp1/f32 = as float32! 7.89
  --test-- "nmh4"
    nmsp1/s: "str"
  --assert 13 = length? s
  --test-- "nmh5"
    nmh5-i: 1
    nmsp1/fn :nmh5-i
  --assert 789 = nmh5-i
  --test-- "nmh6"
    nmh6-i: 1
    fn :nmh6-i
  --assert 987 = nmh6-i
  --test-- "nmh7"
    nmh7-i: 2
  --assert 4 = nmsp1/fn2 nmh7-i
  --assert 6 = fn2 nmh7-i
  --test-- "nmh8"
    st/a: 1
    st/b: 2
    nmsp1/st/a: 100
    nmsp1/st/b: 200
  --assert 1 = st/a
  --assert 2 = st/b

===end-group===

===start-group=== "initialisation"
    nmsp2: context [
      i: 2
      j: 3
      k: 0
      s: "12345"
      st: declare struct! [
        a [integer!]
        b [c-string!]
        c [float!]
        d [integer!]
      ]

      k: i * j
      s/1: #"h"
      s/2: #"e"
      s/3: #"l"
      s/4: #"l"
      s/5: #"o"
      st/a: 1
      st/b: "hello"
      st/c: 12345.678
      st/d: 1
      until [
        i: i * j
        j: j - 1
        j < 1
      ]
    ]
  --test-- "nmi1"
  --assert nmsp2/i = 12
  --test-- "nmi2"
  --assert nmsp2/j = 0
  --test-- "nmi3"
  --assert nmsp2/k = 6
  --test-- "nmi4"
  --assert nmsp2/s/1 = #"h"
  --assert nmsp2/s/2 = #"e"
  --assert nmsp2/s/3 = #"l"
  --assert nmsp2/s/4 = #"l"
  --assert nmsp2/s/5 = #"o"
  --test-- "nmi5"
  --assert nmsp2/st/a = 1
  --test-- "nmi6"
  --assert nmsp2/st/b/1 = #"h"
  --assert nmsp2/st/b/2 = #"e"
  --assert nmsp2/st/b/3 = #"l"
  --assert nmsp2/st/b/4 = #"l"
  --assert nmsp2/st/b/5 = #"o"
  --test-- "nmi7"
  --assert nmsp2/st/c = 12345.678
  --test-- "nmi8"
  --assert nmsp2/st/d = 1

===end-group===

===start-group=== "multiple"
    nmspa: context [
      i: 1
    ]
    nmspb: context [
      i: 2
    ]
    nmspc: context [
      i: 3
    ]
    nmspd: context [
      i: 4
    ]
    nmspe: context [
      i: 5
    ]
    nmspf: context [
      i: 6
    ]
    nmspg: context [
      i: 7
    ]
    nmsph: context [
      i: 8
    ]
    nmspi: context [
      i: 9
    ]
    nmspj: context [
      i: 10
    ]
    nmspk: context [
      i: 11
    ]
  --test-- "nmm1"
  --assert nmspa/i = 1
  --assert nmspb/i = 2
  --assert nmspc/i = 3
  --assert nmspd/i = 4
  --assert nmspe/i = 5
  --assert nmspf/i = 6
  --assert nmspg/i = 7
  --assert nmsph/i = 8
  --assert nmspi/i = 9
  --assert nmspj/i = 10
  --assert nmspk/i = 11

===end-group===

===start-group=== "global access"
  --test-- "nmga1"
    i2: 0
    j: 3
    nmsp3: context [
      i: 2
      k: i * j
      i2: 4
    ]
  --assert nmsp3/k = 6
  --assert nmsp3/i2 = 4
  --assert i2 = 0
  --test-- "nmga2"
      j3: 1
    nmsp4: context [
      i3: 2
      k3: i3 * j3
      i4: 4
    ]
    i4: 0
    j3: 3
  --assert nmsp4/k3 = 2
  --assert i4 = 0
===end-group===

===start-group=== "pointers"
  --test-- "nmp1"
    i: 12345
    nmsp5: context [
      pi: declare pointer! [integer!]
    ]
    nmsp5/pi: :i
  --assert nmsp5/pi/value = 12345
  ; --test-- "nmp2"						;-- getting a pointer on a variable in a context using a path
  ;   pi: declare pointer! [integer!]	;-- is not a supported feature. Use a local function to
  ;   nmsp6: context [					;-- get such pointer.
  ;     i: 12345
  ;   ]
  ;   pi: :nmsp6/i
  ; --assert pi/value = 12345
  --test-- "nmp3"
    nmsp6a: context [
      i: 67890
      get-addr-i: func [
        return: [pointer! [integer!]]
      ][
        :i
      ]
    ]
    pinmp3: declare pointer! [integer!]
    pinmp3: nmsp6a/get-addr-i
  --assert 67890 = pinmp3/value

===end-group===

===start-group=== "nesting"
  --test-- "nmm1"
    nmsp7: context [
      i: 0
      nmsp7-1: context [
        i: 1
        j: i * nmsp7/i
        nmsp7-2: context [
          i: 2
          j: i * nmsp7/i
          k: i * nmsp7/nmsp7-1/i
          nmsp7-3: context [
            i: 3
            j: i * nmsp7/i
            k: i * nmsp7/nmsp7-1/i
            l: i * nmsp7/nmsp7-1/nmsp7-2/i
          ]
          --assert i = 2
          --assert j = 0
          --assert k = 2
		  --assert nmsp7/i = 0
		  --assert nmsp7/nmsp7-1/i = 1
		  --assert nmsp7/nmsp7-1/j = 0
        ]
        --assert i = 1
        --assert j = 0
        --assert nmsp7/i = 0
      ]
      --assert i = 0
    ]
  --assert nmsp7/i = 0
  --assert nmsp7/nmsp7-1/i = 1
  --assert nmsp7/nmsp7-1/j = 0
  --assert nmsp7/nmsp7-1/nmsp7-2/i = 2
  --assert nmsp7/nmsp7-1/nmsp7-2/j = 0
  --assert nmsp7/nmsp7-1/nmsp7-2/k = 2
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/i = 3
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/j = 0
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/k = 3
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/l = 6
===end-group===

===start-group=== "include"
  --test-- "nminc1"
    nmsp8: context [
      #include %namespace-test-include.reds
    ]
  --assert 54321 = nmsp8/i

===end-group===

===start-group=== "libs"
    nmsp-lib: context [
      #import [
        LIBM-file cdecl [
          abs-int: "abs" [
            i       [integer!]
            return: [integer!]
          ]
        ]
      ]
      #import [
        LIBC-file cdecl [
          strlen: "strlen" [
            str     [c-string!]
            return: [integer!]
          ]
        ]
      ]
    ]
  --test-- "nmlibs1"
  --assert 1 = nmsp-lib/abs-int -1
  --test-- "nmlibs2"
  --assert 11 = nmsp-lib/strlen "hello world"

===end-group===

===start-group=== "cross-reference"

	nmxr1: context [c: 789 fooo: func [][nmxr2/e: 123]]
	nmxr2: context [e: 456 f: nmxr1/c]

  --test-- "ns-cross-1"
	--assert nmxr2/e = 456
	nmxr1/fooo
	--assert nmxr2/e = 123

  --test-- "ns-cross-2"
	--assert nmxr2/f = 789

===end-group===

===start-group=== "with"
  --test-- "nsw1"
    nsw1-nsp: context [b: 123]
    with nsw1-nsp [
      --assert b = 123
    ]

  --test-- "nsw2"
    nsw2-nsp1: context [b: 123]
    nsw2-nsp2: context [b: 456]
    with [nsw2-nsp1 nsw2-nsp2] [
      --assert b = 123
      --assert nsw2-nsp1/b = 123
      --assert nsw2-nsp2/b = 456
    ]

  --test-- "nsw3"
    nsw3-nsp1: context [z: declare pointer! [integer!] fooo: func [][nsw3-nsp2/e: 123]]
    nsw3-nsp2: context [e: 456]

    with nsw3-nsp1 [
      c: 123
      z: null
    ]
	--assert nsw3-nsp1/z = null

	  e: -1
	  with [nsw3-nsp1 nsw3-nsp2][
	    fooo
	    --assert e = 123
	  ]
	--assert e = -1

	--test-- "nsw4"
    nsw4-nsp1: context [e: 456]
    nsw4-nsp2: context [fooo: func [][e: 123]]
    with [nsw4-nsp1 nsw4-nsp2] [
      fooo
      --assert e = 456
    ]

===end-group===

===start-group=== "System/Words"

  --test-- "nssw1"
    nssw1-a: 1
    nssw1-nmsp: context [
      nssw1-a: 2
      --assert 1 = system/words/nssw1-a
      --assert 2 = nssw1-a
      system/words/nssw1-a: 3
    ]
  --assert nssw1-a = 3

  --test-- "nssw2"
    nssw2-i: 1
    nssw2-nmsp: context [
      nssw2-i: 2
      pi: declare pointer! [integer!]
      pi: :nssw2-i
      --assert pi/value = 2
    ]
  --assert nssw2-i = 1

===end-group===

===start-group=== "context as local variable"
  ;--test-- "nscaslv1"
  ;  nsca1-nsmp1: context [
  ;    context: 1  							;-- this is not allowed as contexts can be nested, so
  ;  ]										;-- you can't redefine 'context word there, but only
  ;--assert nsca1-nsmp1/context 1			;-- in a function's body.
  --test-- "nscasv2"
    nsca2-f: function [
      return: [integer!]
      /local
        context
    ][
      context: 1
      context
    ]
  --assert nsca2-f = 1

===end-group===

===start-group=== "acessing alias from context"

  --test-- "nsaa1 - issue #237"
    nssa1-c: context [
      s!: alias struct! [val [integer!]]
      s: declare s!
      s/val: 100
    ]
    nssa1-f: function [
      p [nssa1-c/s!]
    ][
      P/val
    ]
  --assert 100 = nssa1-f

  --test-- "nsaa2 - issue #238'
    nssa2-c: context [
      s!: alias struct! [val [integer!]]
      s: declare s!
      s/val: 200
    ]

    with nssa2-c [
      nssa2-f: function [
        p [s!]
      ][
        p/val
      ]
    ]
  --assert 200 = nssa-f

===end-group===

~~~end-file~~~

Red/System [
	Title:   "Red/System null test script"
	Author:  "Nenad Rakocevic & Peter W A Wood"
	File: 	 %namespace-test.reds
	Rights:  "Copyright (C) 2011 Nenad Rakocevic & Peter W A Wood. All rights reserved."
	License: "BSD-3 - https://github.com/dockimbel/Red/blob/origin/BSD-3-License.txt"
]

#include %../../../../quick-test/quick-test.reds

~~~start-file~~~ "namespace"

    nmsp1: context [
      i: 123
      f: 1.23
      f32: as float32! 2.46
      l: true
      s: "my string"
      fn: func [pi [pointer! [integer!]] return: [integer!]] [pi/value: 789 789]
      fn2: func [
        i [integer!]
        return: [integer!]
      ][ 2 * i]
      st: declare struct! [
        a [integer!]
        b [integer!]
      ]
    ]

    i: 987
	ctx: context [
		i: 123
		j: "test"
		foo: func [return: [integer!]][
			i: i + 1
			i
		]
		--test-- "in-ns1"
		--assert 124 = foo
	]

===start-group=== "basic"

  --test-- "ns1"
  --assert 123 = nmsp1/i
  --test-- "ns2"
  --assert 1.23 = nmsp1/f
  --test-- "ns3"
  --assert (as float32! 2.46) = nmsp1/f32
  --test-- "ns4"
  --assert nmsp1/l
  --test-- "ns5"
  --assert nmsp1/s/1 = #"m"
  --assert nmsp1/s/2 = #"y"
  --assert nmsp1/s/3 = #" "
  --assert nmsp1/s/4 = #"s"
  --assert nmsp1/s/5 = #"t"
  --assert nmsp1/s/6 = #"r"
  --assert nmsp1/s/7 = #"i"
  --assert nmsp1/s/8 = #"n"
  --assert nmsp1/s/9 = #"g"
  --test-- "ns6"
    nmsp1/s: "hello"
  --assert 5 = length? nmsp1/s
  --test-- "ns7"
    ns1-b-i: 0
  --assert 789 = nmsp1/fn :ns1-b-i
  --test-- "ns8"
    ns1-b-i: 4
  --assert 8 = nmsp1/fn2 ns1-b-i
  --test-- "ns9"
    nmsp1/st/a: 1
  --assert nmsp1/st/a = 1
  --test-- "ns10"
  --assert ctx/j/1 = #"t"
  --test-- "ns11"
  --assert ctx/foo = 125
  --test-- "ns12"
    ctx/i: ctx/i + 1
  --assert ctx/i = 126
  --assert i = 987
  --test-- "ns13"
    ns13i: 1
    ns13i-nsp: context [
      ns13i: 2
      get-ns13i: func [return: [integer!]] [ns13i]
    ]
  --assert 2 = ns13i-nsp/get-ns13i

===end-group===

===start-group=== "hiding"
    i: 321
    f: 3.21
    f32: as float32! 6.42
    l: false
    s: "not my string"
    fn: func [pi [pointer! [integer!]]] [pi/value: 987]
    fn2: func[
        i [integer!]
        return: [integer!]
      ][ 3 * i]
    st: declare struct! [
        a [integer!]
        b [integer!]
    ]

  --test-- "nmh1"
    nmsp1/i: 789
  --assert i = 321
  --test-- "nmh2"
    nmsp1/f: 7.89
  --assert f = 3.21
  --test-- "nmh3"
    nmsp1/f32: as float32! 7.89
  --assert nmsp1/f32 = as float32! 7.89
  --test-- "nmh4"
    nmsp1/s: "str"
  --assert 13 = length? s
  --test-- "nmh5"
    nmh5-i: 1
    nmsp1/fn :nmh5-i
  --assert 789 = nmh5-i
  --test-- "nmh6"
    nmh6-i: 1
    fn :nmh6-i
  --assert 987 = nmh6-i
  --test-- "nmh7"
    nmh7-i: 2
  --assert 4 = nmsp1/fn2 nmh7-i
  --assert 6 = fn2 nmh7-i
  --test-- "nmh8"
    st/a: 1
    st/b: 2
    nmsp1/st/a: 100
    nmsp1/st/b: 200
  --assert 1 = st/a
  --assert 2 = st/b

===end-group===

===start-group=== "initialisation"
    nmsp2: context [
      i: 2
      j: 3
      k: 0
      s: "12345"
      st: declare struct! [
        a [integer!]
        b [c-string!]
        c [float!]
        d [integer!]
      ]

      k: i * j
      s/1: #"h"
      s/2: #"e"
      s/3: #"l"
      s/4: #"l"
      s/5: #"o"
      st/a: 1
      st/b: "hello"
      st/c: 12345.678
      st/d: 1
      until [
        i: i * j
        j: j - 1
        j < 1
      ]
    ]
  --test-- "nmi1"
  --assert nmsp2/i = 12
  --test-- "nmi2"
  --assert nmsp2/j = 0
  --test-- "nmi3"
  --assert nmsp2/k = 6
  --test-- "nmi4"
  --assert nmsp2/s/1 = #"h"
  --assert nmsp2/s/2 = #"e"
  --assert nmsp2/s/3 = #"l"
  --assert nmsp2/s/4 = #"l"
  --assert nmsp2/s/5 = #"o"
  --test-- "nmi5"
  --assert nmsp2/st/a = 1
  --test-- "nmi6"
  --assert nmsp2/st/b/1 = #"h"
  --assert nmsp2/st/b/2 = #"e"
  --assert nmsp2/st/b/3 = #"l"
  --assert nmsp2/st/b/4 = #"l"
  --assert nmsp2/st/b/5 = #"o"
  --test-- "nmi7"
  --assert nmsp2/st/c = 12345.678
  --test-- "nmi8"
  --assert nmsp2/st/d = 1

===end-group===

===start-group=== "multiple"
    nmspa: context [
      i: 1
    ]
    nmspb: context [
      i: 2
    ]
    nmspc: context [
      i: 3
    ]
    nmspd: context [
      i: 4
    ]
    nmspe: context [
      i: 5
    ]
    nmspf: context [
      i: 6
    ]
    nmspg: context [
      i: 7
    ]
    nmsph: context [
      i: 8
    ]
    nmspi: context [
      i: 9
    ]
    nmspj: context [
      i: 10
    ]
    nmspk: context [
      i: 11
    ]
  --test-- "nmm1"
  --assert nmspa/i = 1
  --assert nmspb/i = 2
  --assert nmspc/i = 3
  --assert nmspd/i = 4
  --assert nmspe/i = 5
  --assert nmspf/i = 6
  --assert nmspg/i = 7
  --assert nmsph/i = 8
  --assert nmspi/i = 9
  --assert nmspj/i = 10
  --assert nmspk/i = 11

===end-group===

===start-group=== "global access"
  --test-- "nmga1"
    i2: 0
    j: 3
    nmsp3: context [
      i: 2
      k: i * j
      i2: 4
    ]
  --assert nmsp3/k = 6
  --assert nmsp3/i2 = 4
  --assert i2 = 0
  --test-- "nmga2"
      j3: 1
    nmsp4: context [
      i3: 2
      k3: i3 * j3
      i4: 4
    ]
    i4: 0
    j3: 3
  --assert nmsp4/k3 = 2
  --assert i4 = 0
===end-group===

===start-group=== "pointers"
  --test-- "nmp1"
    i: 12345
    nmsp5: context [
      pi: declare pointer! [integer!]
    ]
    nmsp5/pi: :i
  --assert nmsp5/pi/value = 12345
  ; --test-- "nmp2"						;-- getting a pointer on a variable in a context using a path
  ;   pi: declare pointer! [integer!]	;-- is not a supported feature. Use a local function to
  ;   nmsp6: context [					;-- get such pointer.
  ;     i: 12345
  ;   ]
  ;   pi: :nmsp6/i
  ; --assert pi/value = 12345
  --test-- "nmp3"
    nmsp6a: context [
      i: 67890
      get-addr-i: func [
        return: [pointer! [integer!]]
      ][
        :i
      ]
    ]
    pinmp3: declare pointer! [integer!]
    pinmp3: nmsp6a/get-addr-i
  --assert 67890 = pinmp3/value

===end-group===

===start-group=== "nesting"
  --test-- "nmm1"
    nmsp7: context [
      i: 0
      nmsp7-1: context [
        i: 1
        j: i * nmsp7/i
        nmsp7-2: context [
          i: 2
          j: i * nmsp7/i
          k: i * nmsp7/nmsp7-1/i
          nmsp7-3: context [
            i: 3
            j: i * nmsp7/i
            k: i * nmsp7/nmsp7-1/i
            l: i * nmsp7/nmsp7-1/nmsp7-2/i
          ]
          --assert i = 2
          --assert j = 0
          --assert k = 2
		  --assert nmsp7/i = 0
		  --assert nmsp7/nmsp7-1/i = 1
		  --assert nmsp7/nmsp7-1/j = 0
        ]
        --assert i = 1
        --assert j = 0
        --assert nmsp7/i = 0
      ]
      --assert i = 0
    ]
  --assert nmsp7/i = 0
  --assert nmsp7/nmsp7-1/i = 1
  --assert nmsp7/nmsp7-1/j = 0
  --assert nmsp7/nmsp7-1/nmsp7-2/i = 2
  --assert nmsp7/nmsp7-1/nmsp7-2/j = 0
  --assert nmsp7/nmsp7-1/nmsp7-2/k = 2
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/i = 3
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/j = 0
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/k = 3
  --assert nmsp7/nmsp7-1/nmsp7-2/nmsp7-3/l = 6
===end-group===

===start-group=== "include"
  --test-- "nminc1"
    nmsp8: context [
      #include %namespace-test-include.reds
    ]
  --assert 54321 = nmsp8/i

===end-group===

===start-group=== "libs"
    nmsp-lib: context [
      #import [
        LIBM-file cdecl [
          abs-int: "abs" [
            i       [integer!]
            return: [integer!]
          ]
        ]
      ]
      #import [
        LIBC-file cdecl [
          strlen: "strlen" [
            str     [c-string!]
            return: [integer!]
          ]
        ]
      ]
    ]
  --test-- "nmlibs1"
  --assert 1 = nmsp-lib/abs-int -1
  --test-- "nmlibs2"
  --assert 11 = nmsp-lib/strlen "hello world"

===end-group===

===start-group=== "cross-reference"

	nmxr1: context [c: 789 fooo: func [][nmxr2/e: 123]]
	nmxr2: context [e: 456 f: nmxr1/c]

  --test-- "ns-cross-1"
	--assert nmxr2/e = 456
	nmxr1/fooo
	--assert nmxr2/e = 123

  --test-- "ns-cross-2"
	--assert nmxr2/f = 789

===end-group===

===start-group=== "with"
  --test-- "nsw1"
    nsw1-nsp: context [b: 123]
    with nsw1-nsp [
      --assert b = 123
    ]

  --test-- "nsw2"
    nsw2-nsp1: context [b: 123]
    nsw2-nsp2: context [b: 456]
    with [nsw2-nsp1 nsw2-nsp2] [
      --assert b = 123
      --assert nsw2-nsp1/b = 123
      --assert nsw2-nsp2/b = 456
    ]

  --test-- "nsw3"
    nsw3-nsp1: context [z: declare pointer! [integer!] fooo: func [][nsw3-nsp2/e: 123]]
    nsw3-nsp2: context [e: 456]

    with nsw3-nsp1 [
      c: 123
      z: null
    ]
	--assert nsw3-nsp1/z = null

	  e: -1
	  with [nsw3-nsp1 nsw3-nsp2][
	    fooo
	    --assert e = 123
	  ]
	--assert e = -1

	--test-- "nsw4"
    nsw4-nsp1: context [e: 456]
    nsw4-nsp2: context [fooo: func [][e: 123]]
    with [nsw4-nsp1 nsw4-nsp2] [
      fooo
      --assert e = 456
    ]

===end-group===

===start-group=== "System/Words"

  --test-- "nssw1"
    nssw1-a: 1
    nssw1-nmsp: context [
      nssw1-a: 2
      --assert 1 = system/words/nssw1-a
      --assert 2 = nssw1-a
      system/words/nssw1-a: 3
    ]
  --assert nssw1-a = 3

  --test-- "nssw2"
    nssw2-i: 1
    nssw2-nmsp: context [
      nssw2-i: 2
      pi: declare pointer! [integer!]
      pi: :nssw2-i
      --assert pi/value = 2
    ]
  --assert nssw2-i = 1

===end-group===

===start-group=== "context as local variable"
  ;--test-- "nscaslv1"
  ;  nsca1-nsmp1: context [
  ;    context: 1  							;-- this is not allowed as contexts can be nested, so
  ;  ]										;-- you can't redefine 'context word there, but only
  ;--assert nsca1-nsmp1/context 1			;-- in a function's body.
  --test-- "nscasv2"
    nsca2-f: function [
      return: [integer!]
      /local
        context
    ][
      context: 1
      context
    ]
  --assert nsca2-f = 1

===end-group===

~~~end-file~~~


TESTS: Added test to cast-test.reds re Issue #317

Red/System [
	Title:   "Red/System datatype casting test script"
	Author:  "Nenad Rakocevic & Peter W A Wood"
	File: 	 %cast-test.reds
	Tabs:	 4
	Rights:  "Copyright (C) 2011-2012 Nenad Rakocevic & Peter W A Wood. All rights reserved."
	License: "BSD-3 - https://github.com/dockimbel/Red/blob/origin/BSD-3-License.txt"
]

#include %../../../../quick-test/quick-test.reds

~~~start-file~~~ "cast"

===start-group=== "cast from byte!"

	--test-- "byte-cast-1"
	--assert 65 = as integer! #"A"

	--test-- "byte-cast-2"
	  cast-b: #"A"
	  cast-i: 65
	--assert cast-i = as integer! cast-b

	--test-- "byte-cast-3"
	--assert false = as logic! #"^(00)"

	--test-- "byte-cast-4"
    cast-b: #"^(00)"
	  l: false
	--assert l = as logic! cast-b

	--test-- "byte-cast-5"
	--assert true = as logic! #"A"

	--test-- "byte-cast-6"
	  cast-b: #"A"
	  l: true
	--assert l = as logic! cast-b

	--test-- "byte-cast-7"
	--assert true = as logic! #"^(FF)"

	--test-- "byte-cast-8"
	  cast-b: #"^(FF)"
	  l: true
	--assert l = as logic! cast-b

	--test-- "byte-cast-9"							;-- issue #158
	  a: as-byte 10h
	  b: as-byte 80h
	--assert 10h = as-integer a

	--test-- "byte-cast-10"							;-- issue #159
	  a: as-byte 10h
	  b: as-byte 80h
	  c: as-integer a
	--assert 10h = c

	--test-- "byte-cast-11"							;-- issue #160
	  a: as-byte 1
	  b: as-byte 2
	  --assert (as byte-ptr! (as-integer a) * 2) = (as byte-ptr! 2)
	  --assert (as byte-ptr! (as-integer a) << 2) = (as byte-ptr! 4)

	--test-- "byte-cast-12"							;-- issue #161
	  a: as-byte 1
	  b: as-byte 2
	  c: (as-integer b) << 16 or as-integer a
	  --assert 00020001h = c

	--test-- "byte-cast-13"							;-- issue #162
	  sb: declare struct! [
	      a   [byte!]
	      b   [byte!]
	  ]
	  sb/a: as-byte 0
	  sb/b: as-byte 1
	  --assert not as-logic sb/a

	--test-- "byte-cast-13"							;-- issue #150
	 s!: alias struct! [
	     a   [byte!]
	     b   [byte!]
	     c   [byte!]
	     d   [byte!]
	 ]
	 t: declare s!
	 t/a: as-byte 1
	 t/b: as-byte 1
	 t/c: as-byte 0
	 t/d: as-byte 0
	 h: as-integer t/a
	 --assert h = 1

	 --test-- "byte-cast-14"              ;-- issue 317
	   bc14-a: as byte! 1
	   bc14-b: as byte! 2
	   bc14-c: as byte! 3
	   bc14-d: as byte! 4
	   bc14-e: as byte! 5
	   bc14-a: as byte! 0
	 --assert #"^(00)" = bc14-a
	 --assert #"^(02)" = bc14-b
	 --assert #"^(03)" = bc14-c
	 --assert #"^(04)" = bc14-d
	 --assert #"^(05)" = bc14-e

===end-group===

===start-group=== "cast from integer!"
comment {
  --test-- "int-cast-1"
  --assert #"^(00)" = as byte! 0
}
  --test-- "int-cast-2"
    i: 0
    cast-test-b: #"^(00)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-3"
  --assert #"^(01)" = as byte! 1

  --test-- "int-cast-4"
    i: 1
    cast-test-b: #"^(01)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-5"
  --assert #"^(FF)" = as byte! 255

  --test-- "int-cast-6"
    i: 255
    cast-test-b: #"^(FF)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-7"
  --assert #"^(00)" = as byte! 256

  --test-- "int-cast-8"
    i: 256
    cast-test-b: #"^(00)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-9"
  --assert false = as logic! 0

  --test-- "int-cast-10"
    i: 0
    l: false
  --assert l = as logic! i

  --test-- "int-cast-11"
  --assert true = as logic! FFFFFFFFh

  --test-- "int-cast-12"
    i: FFFFFFFFh
    l: true
  --assert l = as logic! i

  --test-- "int-cast-13"
  --assert true = as logic! 1

  --test-- "int-cast-14"
    i: 1
    l: true
  --assert l = as logic! i

  --test-- "int-cast-15"
    cs: "Hello"
    cs2: ""
    i: as integer! cs
    i: i + 1
    cs2: as c-string! i
  --assert cs2/1 = #"e"
  --assert 4 = length? cs2

  --test-- "int-cast-16"           ;; This test assumes 32-bit target
    i: 1
    p: declare pointer! [integer!]
    p: as [pointer! [integer!]] i
    P: P + 1
    i2: as integer! p
  --assert i2 = 5

  --test-- "int-cast-17"           ;; This test assumes 32-bit target
    ;; currently fails as p-int-cast is not declared
    i: 1
    p-int-cast-17: as [pointer! [integer!]] i
    P-int-cast-17: P-int-cast-17 + 1
    i2: as integer! p-int-cast-17
  --assert i2 = 5

  --test-- "int-cast-18"
    i: 1
    s: declare struct! [
      a [integer!]
      b [integer!]
    ]
    s: as [struct! [a [integer!] b [integer!]]] i
    s: s + 1
    i2: as integer! s
  --assert i2 = 9

  --test-- "int-cast-19"
    ic19-logic: either as-logic 0 [
      false
    ][
      true
    ]
  --assert ic19-logic

  --test-- "int-cast-20"
    ic20-dummy: func [return: [integer!]][0]
    ic20-logic: either as-logic ic20-dummy [
       false
    ][
      true
    ]
  --assert ic20-logic

===end-group===

===start-group=== "cast from logic!"

  --test-- "logic-cast-1"
  --assert #"^(01)" = as byte! true

  --test-- "logic-cast-2"
    cast-test-b: #"^(01)"
    l: true
  --assert cast-test-b = as byte! l

  --test-- "logic-cast-3"
  --assert #"^(00)" = as byte! false

  --test-- "logic-cast-4"
    cast-test-b: #"^(00)"
    l: false
  --assert cast-test-b = as byte! l

    --test-- "logic-cast-5"
  --assert 1 = as integer! true

  --test-- "logic-cast-6"
    i: 1
    l: true
  --assert i = as integer! l

  --test-- "logic-cast-7"
  --assert 0 = as integer! false

  --test-- "logic-cast-8"
    i: 0
    l: false
  --assert i = as integer! l

===end-group===

===start-group=== "cast c-string! tests"

  --test-- "c-string-cast-1"
    csc1-str: "Hello, Nenad"
    i: 0
    i: as integer! csc1-str
    i: i + 7
    csc1-str: as c-string! i
  --assert csc1-str/1 = #"N"
  --assert csc1-str/2 = #"e"
  --assert csc1-str/3 = #"n"
  --assert csc1-str/4 = #"a"
  --assert csc1-str/5 = #"d"
  comment {
  --test-- "c-string-cast-2"
  --assert false = as logic! ""
  }
    --test-- "c-string-cast-3"
    csc3-str: ""
  --assert true = as logic! csc3-str

  --test-- "c-string-cast-4"
  --assert true = as logic! "Any old iron, any old iron"

  --test-- "c-string-cast-5"
    csc5-str: "Why not?"
  --assert true = as logic! csc5-str

  --test-- "c-string-cast-6"
    csc6-str: "Tour de France"
    csc6-p: declare pointer! [integer!]
    csc6-p: as [pointer! [integer!]] csc6-str
    csc6-p: csc6-p + 2
    csc6-str2: as c-string! csc6-p
  --assert csc6-str2/1 = #"F"
  --assert csc6-str2/2 = #"r"
  --assert csc6-str2/3 = #"a"
  --assert csc6-str2/4 = #"n"
  --assert csc6-str2/5 = #"c"
  --assert csc6-str2/6 = #"e"

  --test-- "C-string-cast-7"
    csc7-struct: declare struct! [
      c1 [byte!]
      c2 [byte!]
      c3 [byte!]
      c4 [byte!]
      c5 [byte!]
    ]
    csc7-str: "Peter"
    csc7-struct: as [struct! [
      c1 [byte!] c2 [byte!] c3 [byte!] c4 [byte!] c5 [byte!]
    ]] csc7-str
  --assert csc7-struct/c1 = #"P"
  --assert csc7-struct/c2 = #"e"
  --assert csc7-struct/c3 = #"t"
  --assert csc7-struct/c4 = #"e"
  --assert csc7-struct/c5 = #"r"

===end-group===

===start-group=== "cast from pointer!"

  --test-- "csp-1"
    csp1-p: declare pointer! [integer!]
    csp1-p: as [pointer! [integer!]] 256
    i: 0
    i: as integer! csp1-p
  --assert i = 256

  --test-- "csp-2"
    csp2-p: declare pointer! [integer!]
    csp2-p: as [pointer! [integer!]] 0
  --assert false = as logic! csp2-p

  --test-- "csp-3"
    csp3-p: declare pointer! [integer!]
    csp3-p: as [pointer! [integer!]] 1
  --assert true = as logic! csp3-p

  --test-- "csp-4"
    csp4-p: declare pointer! [integer!]
    csp4-p: as [pointer! [integer!]] FFFFFFFFh
  --assert true = as logic! csp4-p

  --test-- "csp-5"
    csp5-p: declare pointer! [integer!]
    csp5-p: as [pointer! [integer!]] 7FFFFFFFh
  --assert true = as logic! csp5-p

  ;; No test for pointer! to c-string! as it would simply
  ;;  duplicate the one of c-string! to pointer!

  --test-- "csp-6"
    csp6-p: declare pointer! [integer!]
    csp6-s: declare struct! [
      a [integer!]
      b [integer!]
    ]
    csp6-s/a: 1
    csp6-s/b: 2
    csp6-p: as [pointer! [integer!]] csp6-s
  --assert csp6-p/value = 1
    csp6-p: csp6-p + 1
  --assert csp6-p/value = 2
    csp6-p: csp6-p - 1
    csp6-s: as [struct! [a [integer!] b [integer!]]] csp6-p
  --assert csp6-s/a = 1
    csp6-p: csp6-p + 1
    csp6-s: as [struct! [a [integer!] b [integer!]]] csp6-p
  --assert csp6-s/a = 2

===end-group===

===start-group=== "cast from struct!"

  ;; no test for cast to integer as it would simply
  ;;  duplicate the test from integer! to struct!

  --test-- "cfstruc-1"
    cfs1-struct: declare struct! [
      a [integer!]
      b [integer!]
    ]
    cfs1-struct: as [struct! [a [integer!] b [integer!]]] 0
  --assert false = as logic! cfs1-struct

  --test-- "cfstruc-2"
    cfs2-struct: declare struct! [
      a [integer!]
      b [integer!]
    ]
  --assert true = as logic! cfs2-struct

  ;; no test for cast to c-string! as it would simply
  ;;  duplicate the test from c-string! to struct!

  ;; no test for cast to pointer! as it would simply
  ;;  duplicate the test from pointer! to struct!

===end-group===

===start-group=== "byte-integer-cast"

  --test-- "bic-1"
    bic-a: as-byte 1
  --assert 1 = as-integer bic-a

  --test-- "bic-2"
    bic-a: as-byte 1
  --assert 65536 = ((as-integer bic-a) << 16)

  --test-- "bic-3"
    bic-a: as-byte 2
  --assert 131072 = ((as-integer bic-a) << 16)

  --test-- "bic-4"
    bic-a: #"^(01)"
  --assert 65537 = (65536 or (as-integer bic-a))

  --test-- "bic-5"
    bic-a: #"^(01)"
    bic-b: #"^(02)"
  --assert 131073 = ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-6"
    bic-a: #"^(01)"
    bic-b: #"^(02)"
  --assert 131073 = ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-7"
    bic-a: #"^(01)"
    bic-b: #"^(02)"
  --assert (as byte-ptr! 131073) = as byte-ptr! ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-8"
    bic-a: as-byte 1
    bic-b: as-byte 2
  --assert 131073 = ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-9"
    bic-a: as-byte 1
    bic-b: as-byte 2
  --assert (as byte-ptr! 131073) = as byte-ptr! ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-10"
    bic-s: declare struct! [
      bic-a [byte!]
      bic-b [byte!]
      bic-c [integer!]
      bic-d [byte!]
      bic-e [byte!]
      bic-f [integer!]
    ]
    bic-s/bic-a: as-byte 0
    bic-s/bic-b: as-byte 1
    bic-s/bic-c: 2
    bic-s/bic-d: as-byte 3
    bic-s/bic-e: as-byte 255
    bic-s/bic-f: 255
  --assert false = as-logic bic-s/bic-a
  --assert true = as-logic bic-s/bic-b
  --assert bic-s/bic-e = as-byte bic-s/bic-f
  --assert bic-s/bic-f = as-integer bic-s/bic-e

===end-group===

===start-group=== "Cast in conditional tests"
    cic-r: false
  --test-- "cic-1"
    cic-d: as-byte 0
    either as-logic cic-d [cic-r: false] [cic-r: true]
  --assert cic-r

  --test-- "cic-2"
    cic-s: declare struct! [
      a   [byte!]
      b   [byte!]
    ]
    cic-s/a: as-byte 0
    cic-s/b: as-byte 1
    either as-logic cic-s/a [cic-r: false] [cic-r: true]
  --assert cic-r

===end-group===

~~~end-file~~~

Red/System [
	Title:   "Red/System datatype casting test script"
	Author:  "Nenad Rakocevic & Peter W A Wood"
	File: 	 %cast-test.reds
	Tabs:	 4
	Rights:  "Copyright (C) 2011-2012 Nenad Rakocevic & Peter W A Wood. All rights reserved."
	License: "BSD-3 - https://github.com/dockimbel/Red/blob/origin/BSD-3-License.txt"
]

#include %../../../../quick-test/quick-test.reds

~~~start-file~~~ "cast"

===start-group=== "cast from byte!"

	--test-- "byte-cast-1"
	--assert 65 = as integer! #"A"

	--test-- "byte-cast-2"
	  cast-b: #"A"
	  cast-i: 65
	--assert cast-i = as integer! cast-b

	--test-- "byte-cast-3"
	--assert false = as logic! #"^(00)"

	--test-- "byte-cast-4"
    cast-b: #"^(00)"
	  l: false
	--assert l = as logic! cast-b

	--test-- "byte-cast-5"
	--assert true = as logic! #"A"

	--test-- "byte-cast-6"
	  cast-b: #"A"
	  l: true
	--assert l = as logic! cast-b

	--test-- "byte-cast-7"
	--assert true = as logic! #"^(FF)"

	--test-- "byte-cast-8"
	  cast-b: #"^(FF)"
	  l: true
	--assert l = as logic! cast-b

	--test-- "byte-cast-9"							;-- issue #158
	  a: as-byte 10h
	  b: as-byte 80h
	--assert 10h = as-integer a

	--test-- "byte-cast-10"							;-- issue #159
	  a: as-byte 10h
	  b: as-byte 80h
	  c: as-integer a
	--assert 10h = c

	--test-- "byte-cast-11"							;-- issue #160
	  a: as-byte 1
	  b: as-byte 2
	  --assert (as byte-ptr! (as-integer a) * 2) = (as byte-ptr! 2)
	  --assert (as byte-ptr! (as-integer a) << 2) = (as byte-ptr! 4)

	--test-- "byte-cast-12"							;-- issue #161
	  a: as-byte 1
	  b: as-byte 2
	  c: (as-integer b) << 16 or as-integer a
	  --assert 00020001h = c

	--test-- "byte-cast-13"							;-- issue #162
	  sb: declare struct! [
	      a   [byte!]
	      b   [byte!]
	  ]
	  sb/a: as-byte 0
	  sb/b: as-byte 1
	  --assert not as-logic sb/a

	--test-- "byte-cast-13"							;-- issue #150
	 s!: alias struct! [
	     a   [byte!]
	     b   [byte!]
	     c   [byte!]
	     d   [byte!]
	 ]
	 t: declare s!
	 t/a: as-byte 1
	 t/b: as-byte 1
	 t/c: as-byte 0
	 t/d: as-byte 0
	 h: as-integer t/a
	 --assert h = 1

===end-group===

===start-group=== "cast from integer!"
comment {
  --test-- "int-cast-1"
  --assert #"^(00)" = as byte! 0
}
  --test-- "int-cast-2"
    i: 0
    cast-test-b: #"^(00)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-3"
  --assert #"^(01)" = as byte! 1

  --test-- "int-cast-4"
    i: 1
    cast-test-b: #"^(01)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-5"
  --assert #"^(FF)" = as byte! 255

  --test-- "int-cast-6"
    i: 255
    cast-test-b: #"^(FF)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-7"
  --assert #"^(00)" = as byte! 256

  --test-- "int-cast-8"
    i: 256
    cast-test-b: #"^(00)"
  --assert cast-test-b = as byte! i

  --test-- "int-cast-9"
  --assert false = as logic! 0

  --test-- "int-cast-10"
    i: 0
    l: false
  --assert l = as logic! i

  --test-- "int-cast-11"
  --assert true = as logic! FFFFFFFFh

  --test-- "int-cast-12"
    i: FFFFFFFFh
    l: true
  --assert l = as logic! i

  --test-- "int-cast-13"
  --assert true = as logic! 1

  --test-- "int-cast-14"
    i: 1
    l: true
  --assert l = as logic! i

  --test-- "int-cast-15"
    cs: "Hello"
    cs2: ""
    i: as integer! cs
    i: i + 1
    cs2: as c-string! i
  --assert cs2/1 = #"e"
  --assert 4 = length? cs2

  --test-- "int-cast-16"           ;; This test assumes 32-bit target
    i: 1
    p: declare pointer! [integer!]
    p: as [pointer! [integer!]] i
    P: P + 1
    i2: as integer! p
  --assert i2 = 5

  --test-- "int-cast-17"           ;; This test assumes 32-bit target
    ;; currently fails as p-int-cast is not declared
    i: 1
    p-int-cast-17: as [pointer! [integer!]] i
    P-int-cast-17: P-int-cast-17 + 1
    i2: as integer! p-int-cast-17
  --assert i2 = 5

  --test-- "int-cast-18"
    i: 1
    s: declare struct! [
      a [integer!]
      b [integer!]
    ]
    s: as [struct! [a [integer!] b [integer!]]] i
    s: s + 1
    i2: as integer! s
  --assert i2 = 9

  --test-- "int-cast-19"
    ic19-logic: either as-logic 0 [
      false
    ][
      true
    ]
  --assert ic19-logic

  --test-- "int-cast-20"
    ic20-dummy: func [return: [integer!]][0]
    ic20-logic: either as-logic ic20-dummy [
       false
    ][
      true
    ]
  --assert ic20-logic

===end-group===

===start-group=== "cast from logic!"

  --test-- "logic-cast-1"
  --assert #"^(01)" = as byte! true

  --test-- "logic-cast-2"
    cast-test-b: #"^(01)"
    l: true
  --assert cast-test-b = as byte! l

  --test-- "logic-cast-3"
  --assert #"^(00)" = as byte! false

  --test-- "logic-cast-4"
    cast-test-b: #"^(00)"
    l: false
  --assert cast-test-b = as byte! l

    --test-- "logic-cast-5"
  --assert 1 = as integer! true

  --test-- "logic-cast-6"
    i: 1
    l: true
  --assert i = as integer! l

  --test-- "logic-cast-7"
  --assert 0 = as integer! false

  --test-- "logic-cast-8"
    i: 0
    l: false
  --assert i = as integer! l

===end-group===

===start-group=== "cast c-string! tests"

  --test-- "c-string-cast-1"
    csc1-str: "Hello, Nenad"
    i: 0
    i: as integer! csc1-str
    i: i + 7
    csc1-str: as c-string! i
  --assert csc1-str/1 = #"N"
  --assert csc1-str/2 = #"e"
  --assert csc1-str/3 = #"n"
  --assert csc1-str/4 = #"a"
  --assert csc1-str/5 = #"d"
  comment {
  --test-- "c-string-cast-2"
  --assert false = as logic! ""
  }
    --test-- "c-string-cast-3"
    csc3-str: ""
  --assert true = as logic! csc3-str

  --test-- "c-string-cast-4"
  --assert true = as logic! "Any old iron, any old iron"

  --test-- "c-string-cast-5"
    csc5-str: "Why not?"
  --assert true = as logic! csc5-str

  --test-- "c-string-cast-6"
    csc6-str: "Tour de France"
    csc6-p: declare pointer! [integer!]
    csc6-p: as [pointer! [integer!]] csc6-str
    csc6-p: csc6-p + 2
    csc6-str2: as c-string! csc6-p
  --assert csc6-str2/1 = #"F"
  --assert csc6-str2/2 = #"r"
  --assert csc6-str2/3 = #"a"
  --assert csc6-str2/4 = #"n"
  --assert csc6-str2/5 = #"c"
  --assert csc6-str2/6 = #"e"

  --test-- "C-string-cast-7"
    csc7-struct: declare struct! [
      c1 [byte!]
      c2 [byte!]
      c3 [byte!]
      c4 [byte!]
      c5 [byte!]
    ]
    csc7-str: "Peter"
    csc7-struct: as [struct! [
      c1 [byte!] c2 [byte!] c3 [byte!] c4 [byte!] c5 [byte!]
    ]] csc7-str
  --assert csc7-struct/c1 = #"P"
  --assert csc7-struct/c2 = #"e"
  --assert csc7-struct/c3 = #"t"
  --assert csc7-struct/c4 = #"e"
  --assert csc7-struct/c5 = #"r"

===end-group===

===start-group=== "cast from pointer!"

  --test-- "csp-1"
    csp1-p: declare pointer! [integer!]
    csp1-p: as [pointer! [integer!]] 256
    i: 0
    i: as integer! csp1-p
  --assert i = 256

  --test-- "csp-2"
    csp2-p: declare pointer! [integer!]
    csp2-p: as [pointer! [integer!]] 0
  --assert false = as logic! csp2-p

  --test-- "csp-3"
    csp3-p: declare pointer! [integer!]
    csp3-p: as [pointer! [integer!]] 1
  --assert true = as logic! csp3-p

  --test-- "csp-4"
    csp4-p: declare pointer! [integer!]
    csp4-p: as [pointer! [integer!]] FFFFFFFFh
  --assert true = as logic! csp4-p

  --test-- "csp-5"
    csp5-p: declare pointer! [integer!]
    csp5-p: as [pointer! [integer!]] 7FFFFFFFh
  --assert true = as logic! csp5-p

  ;; No test for pointer! to c-string! as it would simply
  ;;  duplicate the one of c-string! to pointer!

  --test-- "csp-6"
    csp6-p: declare pointer! [integer!]
    csp6-s: declare struct! [
      a [integer!]
      b [integer!]
    ]
    csp6-s/a: 1
    csp6-s/b: 2
    csp6-p: as [pointer! [integer!]] csp6-s
  --assert csp6-p/value = 1
    csp6-p: csp6-p + 1
  --assert csp6-p/value = 2
    csp6-p: csp6-p - 1
    csp6-s: as [struct! [a [integer!] b [integer!]]] csp6-p
  --assert csp6-s/a = 1
    csp6-p: csp6-p + 1
    csp6-s: as [struct! [a [integer!] b [integer!]]] csp6-p
  --assert csp6-s/a = 2

===end-group===

===start-group=== "cast from struct!"

  ;; no test for cast to integer as it would simply
  ;;  duplicate the test from integer! to struct!

  --test-- "cfstruc-1"
    cfs1-struct: declare struct! [
      a [integer!]
      b [integer!]
    ]
    cfs1-struct: as [struct! [a [integer!] b [integer!]]] 0
  --assert false = as logic! cfs1-struct

  --test-- "cfstruc-2"
    cfs2-struct: declare struct! [
      a [integer!]
      b [integer!]
    ]
  --assert true = as logic! cfs2-struct

  ;; no test for cast to c-string! as it would simply
  ;;  duplicate the test from c-string! to struct!

  ;; no test for cast to pointer! as it would simply
  ;;  duplicate the test from pointer! to struct!

===end-group===

===start-group=== "byte-integer-cast"

  --test-- "bic-1"
    bic-a: as-byte 1
  --assert 1 = as-integer bic-a

  --test-- "bic-2"
    bic-a: as-byte 1
  --assert 65536 = ((as-integer bic-a) << 16)

  --test-- "bic-3"
    bic-a: as-byte 2
  --assert 131072 = ((as-integer bic-a) << 16)

  --test-- "bic-4"
    bic-a: #"^(01)"
  --assert 65537 = (65536 or (as-integer bic-a))

  --test-- "bic-5"
    bic-a: #"^(01)"
    bic-b: #"^(02)"
  --assert 131073 = ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-6"
    bic-a: #"^(01)"
    bic-b: #"^(02)"
  --assert 131073 = ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-7"
    bic-a: #"^(01)"
    bic-b: #"^(02)"
  --assert (as byte-ptr! 131073) = as byte-ptr! ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-8"
    bic-a: as-byte 1
    bic-b: as-byte 2
  --assert 131073 = ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-9"
    bic-a: as-byte 1
    bic-b: as-byte 2
  --assert (as byte-ptr! 131073) = as byte-ptr! ((as-integer bic-b) << 16 or as-integer bic-a)

  --test-- "bic-10"
    bic-s: declare struct! [
      bic-a [byte!]
      bic-b [byte!]
      bic-c [integer!]
      bic-d [byte!]
      bic-e [byte!]
      bic-f [integer!]
    ]
    bic-s/bic-a: as-byte 0
    bic-s/bic-b: as-byte 1
    bic-s/bic-c: 2
    bic-s/bic-d: as-byte 3
    bic-s/bic-e: as-byte 255
    bic-s/bic-f: 255
  --assert false = as-logic bic-s/bic-a
  --assert true = as-logic bic-s/bic-b
  --assert bic-s/bic-e = as-byte bic-s/bic-f
  --assert bic-s/bic-f = as-integer bic-s/bic-e

===end-group===

===start-group=== "Cast in conditional tests"
    cic-r: false
  --test-- "cic-1"
    cic-d: as-byte 0
    either as-logic cic-d [cic-r: false] [cic-r: true]
  --assert cic-r

  --test-- "cic-2"
    cic-s: declare struct! [
      a   [byte!]
      b   [byte!]
    ]
    cic-s/a: as-byte 0
    cic-s/b: as-byte 1
    either as-logic cic-s/a [cic-r: false] [cic-r: true]
  --assert cic-r

===end-group===

~~~end-file~~~


FEAT: extended definitions for low-level JNI bridge.

Red/System [
	Title:   "JVM bridge"
	Author:  "Nenad Rakocevic, Kaj de Vos"
	File: 	 %JNI.reds
	Tabs:	 4
	Rights:  "Copyright (C) 2013 Nenad Rakocevic, Kaj de Vos. All rights reserved."
	License: {
		Distributed under the Boost Software License, Version 1.0.
		See https://github.com/dockimbel/Red/blob/master/BSL-License.txt
	}
]

#define func-ptr!	integer!

#define jmethodID!	int-ptr!
#define jint!		integer!
#define jobject!	int-ptr!
#define jarray!		int-ptr!
#define jclass!		int-ptr!
#define jstring!	int-ptr!
#define jboolean!	int-ptr!

#define JNI-ptr!	[struct! [jni [JNI!]]]
#define JVM-ptr!	[struct! [ptr [JVM!]]]

#switch OS [
	Windows  [#define JNICALL stdcall]
	#default [#define JNICALL cdecl]
]

#define JNI_FALSE	#"^(00)"
#define JNI_TRUE  	#"^(01)"

#enum version! [
	version-1.1:	00010001h
	version-1.2:	00010002h
	version-1.4:	00010004h
	version-1.6:	00010006h
]

JVM!: alias struct! [
    reserved0					[int-ptr!]
    reserved1					[int-ptr!]
    reserved2					[int-ptr!]

    DestroyJavaVM 				[function! [[JNICALL] vm [JVM-ptr!] return: [jint!]]]
	AttachCurrentThread			[function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] args [byte-ptr!] return: [jint!]]]
	DetachCurrentThread 		[function! [[JNICALL] vm [JVM-ptr!] return: [jint!]]]
    GetEnv						[function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] version [integer!] return: [jint!]]]
    AttachCurrentThreadAsDaemon [function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] args [byte-ptr!] return: [jint!]]]
]

JNI!: alias struct! [
    reserved0					[int-ptr!]
    reserved1					[int-ptr!]
    reserved2					[int-ptr!]
    reserved3					[int-ptr!]

	GetVersion					[func-ptr!]
	DefineClass					[func-ptr!]
	FindClass					[function! [[JNICALL] env [JNI-ptr!] name [c-string!] return: [jclass!]]]
	FromReflectedMethod			[function! [[JNICALL] env [JNI-ptr!] method [jobject!] return: [jmethodID!]]]
	FromReflectedField			[func-ptr!]
	ToReflectedMethod			[func-ptr!]
	GetSuperclass				[func-ptr!]
	IsAssignableFrom			[func-ptr!]
	ToReflectedField			[func-ptr!]

	Throw						[func-ptr!]
	ThrowNew					[func-ptr!]
	ExceptionOccurred			[func-ptr!]
	ExceptionDescribe			[func-ptr!]
	ExceptionClear				[function! [[JNICALL] env [JNI-ptr!]]]
	FatalError					[func-ptr!]

	PushLocalFrame				[func-ptr!]
	PopLocalFrame				[func-ptr!]

	NewGlobalRef				[function! [[JNICALL] env [JNI-ptr!] obj [jobject!] return: [jobject!]]]
	DeleteGlobalRef				[function! [[JNICALL] env [JNI-ptr!] ref [jobject!]]]
	DeleteLocalRef				[function! [[JNICALL] env [JNI-ptr!] obj [jobject!]]]
	IsSameObject				[func-ptr!]
	NewLocalRef					[func-ptr!]
	EnsureLocalCapacity			[func-ptr!]

	AllocObject					[func-ptr!]
	NewObject					[function! [[JNICALL variadic] return: [jobject!]]] ;-- stack frame is manually constructed
	NewObjectV					[func-ptr!]
	NewObjectA					[function! [[JNICALL custom] return: [jobject!]]]

	GetObjectClass				[function! [[JNICALL] env [JNI-ptr!] obj [jobject!] return: [jclass!]]]
	IsInstanceOf				[func-ptr!]
	GetMethodID					[function! [[JNICALL] env [JNI-ptr!] class [jclass!] name [c-string!] sig [c-string!] return: [jmethodID!]]]

	CallObjectMethod			[function! [[JNICALL variadic] return: [jobject!]]]
	CallObjectMethodV			[func-ptr!]
	CallObjectMethodA			[function! [[JNICALL custom] return: [jobject!]]]

	CallBooleanMethod			[func-ptr!]
	CallBooleanMethodV			[func-ptr!]
	CallBooleanMethodA			[function! [[JNICALL custom] return: [jboolean!]]]

	CallByteMethod				[func-ptr!]
	CallByteMethodV				[func-ptr!]
	CallByteMethodA				[function! [[JNICALL custom] return: [jobject!]]]

	CallCharMethod				[func-ptr!]
	CallCharMethodV				[func-ptr!]
	CallCharMethodA				[function! [[JNICALL custom] return: [jint!]]]

	CallShortMethod				[func-ptr!]
	CallShortMethodV			[func-ptr!]
	CallShortMethodA			[function! [[JNICALL custom] return: [jint!]]]

	CallIntMethod				[func-ptr!]
	CallIntMethodV				[func-ptr!]
	CallIntMethodA				[function! [[JNICALL custom] return: [jint!]]]

	CallLongMethod				[func-ptr!]
	CallLongMethodV				[func-ptr!]
	CallLongMethodA				[function! [[JNICALL custom] return: [jint!]]]

	CallFloatMethod				[func-ptr!]
	CallFloatMethodV			[func-ptr!]
	CallFloatMethodA			[function! [[JNICALL custom] return: [jobject!]]]

	CallDoubleMethod			[func-ptr!]
	CallDoubleMethodV			[func-ptr!]
	CallDoubleMethodA			[function! [[JNICALL custom] return: [jobject!]]]

	CallVoidMethod				[function! [[JNICALL variadic]]]
	CallVoidMethodV				[func-ptr!]
	CallVoidMethodA				[function! [[JNICALL custom]]]

	CallNonvirtualObjectMethod	[func-ptr!]
	CallNonvirtualObjectMethodV	[func-ptr!]
	CallNonvirtualObjectMethodA	[function! [[JNICALL custom] return: [jobject!]]]

	CallNonvirtualBooleanMethod	 [func-ptr!]
	CallNonvirtualBooleanMethodV [func-ptr!]
	CallNonvirtualBooleanMethodA [func-ptr!]

	CallNonvirtualByteMethod	[func-ptr!]
	CallNonvirtualByteMethodV	[func-ptr!]
	CallNonvirtualByteMethodA	[func-ptr!]

	CallNonvirtualCharMethod	[func-ptr!]
	CallNonvirtualCharMethodV	[func-ptr!]
	CallNonvirtualCharMethodA	[func-ptr!]

	CallNonvirtualShortMethod	[func-ptr!]
	CallNonvirtualShortMethodV	[func-ptr!]
	CallNonvirtualShortMethodA	[func-ptr!]

	CallNonvirtualIntMethod		[func-ptr!]
	CallNonvirtualIntMethodV	[func-ptr!]
	CallNonvirtualIntMethodA	[func-ptr!]

	CallNonvirtualLongMethod	[func-ptr!]
	CallNonvirtualLongMethodV	[func-ptr!]
	CallNonvirtualLongMethodA	[func-ptr!]

	CallNonvirtualFloatMethod	[func-ptr!]
	CallNonvirtualFloatMethodV	[func-ptr!]
	CallNonvirtualFloatMethodA	[func-ptr!]

	CallNonvirtualDoubleMethod	[func-ptr!]
	CallNonvirtualDoubleMethodV	[func-ptr!]
	CallNonvirtualDoubleMethodA	[func-ptr!]

	CallNonvirtualVoidMethod	[func-ptr!]
	CallNonvirtualVoidMethodV	[func-ptr!]
	CallNonvirtualVoidMethodA	[func-ptr!]

	GetFieldID					[func-ptr!]
	GetObjectField				[func-ptr!]
	GetBooleanField				[func-ptr!]
	GetByteField				[func-ptr!]
	GetCharField				[func-ptr!]
	GetShortField				[func-ptr!]
	GetIntField					[func-ptr!]
	GetLongField				[func-ptr!]
	GetFloatField				[func-ptr!]
	GetDoubleField				[func-ptr!]

	SetObjectField				[func-ptr!]
	SetBooleanField				[func-ptr!]
	SetByteField				[func-ptr!]
	SetCharField				[func-ptr!]
	SetShortField				[func-ptr!]
	SetIntField					[func-ptr!]
	SetLongField				[func-ptr!]
	SetFloatField				[func-ptr!]
	SetDoubleField				[func-ptr!]

	GetStaticMethodID			[function! [[JNICALL] env [JNI-ptr!] class [jclass!] name [c-string!] sig [c-string!] return: [jmethodID!]]]

	CallStaticObjectMethod		[function! [[JNICALL variadic] return: [jobject!]]]
	CallStaticObjectMethodV		[func-ptr!]
	CallStaticObjectMethodA		[func-ptr!]

	CallStaticBooleanMethod		[func-ptr!]
	CallStaticBooleanMethodV	[func-ptr!]
	CallStaticBooleanMethodA	[func-ptr!]

	CallStaticByteMethod		[func-ptr!]
	CallStaticByteMethodV		[func-ptr!]
	CallStaticByteMethodA		[func-ptr!]

	CallStaticCharMethod		[func-ptr!]
	CallStaticCharMethodV		[func-ptr!]
	CallStaticCharMethodA		[func-ptr!]

	CallStaticShortMethod		[func-ptr!]
	CallStaticShortMethodV		[func-ptr!]
	CallStaticShortMethodA		[func-ptr!]

	CallStaticIntMethod			[func-ptr!]
	CallStaticIntMethodV		[func-ptr!]
	CallStaticIntMethodA		[func-ptr!]

	CallStaticLongMethod		[func-ptr!]
	CallStaticLongMethodV		[func-ptr!]
	CallStaticLongMethodA		[func-ptr!]

	CallStaticFloatMethod		[func-ptr!]
	CallStaticFloatMethodV		[func-ptr!]
	CallStaticFloatMethodA		[func-ptr!]

	CallStaticDoubleMethod		[func-ptr!]
	CallStaticDoubleMethodV		[func-ptr!]
	CallStaticDoubleMethodA		[func-ptr!]

	CallStaticVoidMethod		[func-ptr!]
	CallStaticVoidMethodV		[func-ptr!]
	CallStaticVoidMethodA		[func-ptr!]

	GetStaticFieldID			[func-ptr!]
	GetStaticObjectField		[func-ptr!]
	GetStaticBooleanField		[func-ptr!]
	GetStaticByteField			[func-ptr!]
	GetStaticCharField			[func-ptr!]
	GetStaticShortField			[func-ptr!]
	GetStaticIntField			[func-ptr!]
	GetStaticLongField			[func-ptr!]
	GetStaticFloatField			[func-ptr!]
	GetStaticDoubleField		[func-ptr!]

	SetStaticObjectField		[func-ptr!]
	SetStaticBooleanField		[func-ptr!]
	SetStaticByteField			[func-ptr!]
	SetStaticCharField			[func-ptr!]
	SetStaticShortField			[func-ptr!]
	SetStaticIntField			[func-ptr!]
	SetStaticLongField			[func-ptr!]
	SetStaticFloatField			[func-ptr!]
	SetStaticDoubleField		[func-ptr!]

	NewString					[func-ptr!]
	GetStringLength				[func-ptr!]
	GetStringChars				[func-ptr!]
	ReleaseStringChars			[func-ptr!]

	NewStringUTF				[function! [[JNICALL] env [JNI-ptr!] bytes [c-string!] return: [jobject!]]]
	GetStringUTFLength			[func-ptr!]
	GetStringUTFChars			[function! [[JNICALL] env [JNI-ptr!] str [jstring!] isCopy [struct! [c [jboolean!]]] return: [c-string!]]]
	ReleaseStringUTFChars		[function! [[JNICALL] env [JNI-ptr!] str [jstring!] buf [c-string!]]]

	GetArrayLength				[function! [[JNICALL] env [JNI-ptr!] array [jobject!] return: [jint!]]]
	NewObjectArray				[function! [[JNICALL] env [JNI-ptr!] size [jint!] type [jclass!] init [jobject!] return: [jarray!]]]
	GetObjectArrayElement		[function! [[JNICALL] env [JNI-ptr!] array [jobject!] idx [jint!] return: [jobject!]]]
	SetObjectArrayElement		[function! [[JNICALL] env [JNI-ptr!] array [jobject!] idx [jint!] obj [jobject!] return: [jobject!]]]

	NewBooleanArray				[func-ptr!]
	NewByteArray				[func-ptr!]
	NewCharArray				[func-ptr!]
	NewShortArray				[func-ptr!]
	NewIntArray					[func-ptr!]
	NewLongArray				[func-ptr!]
	NewFloatArray				[func-ptr!]
	NewDoubleArray				[func-ptr!]

	GetBooleanArrayElements		[func-ptr!]
	GetByteArrayElements		[func-ptr!]
	GetCharArrayElements		[func-ptr!]
	GetShortArrayElements		[func-ptr!]
	GetIntArrayElements			[func-ptr!]
	GetLongArrayElements		[func-ptr!]
	GetFloatArrayElements		[func-ptr!]
	GetDoubleArrayElements		[func-ptr!]

	ReleaseBooleanArrayElements	[func-ptr!]
	ReleaseByteArrayElements	[func-ptr!]
	ReleaseCharArrayElements	[func-ptr!]
	ReleaseShortArrayElements	[func-ptr!]
	ReleaseIntArrayElements		[func-ptr!]
	ReleaseLongArrayElements	[func-ptr!]
	ReleaseFloatArrayElements	[func-ptr!]
	ReleaseDoubleArrayElements	[func-ptr!]

	GetBooleanArrayRegion		[func-ptr!]
	GetByteArrayRegion			[func-ptr!]
	GetCharArrayRegion			[func-ptr!]
	GetShortArrayRegion			[func-ptr!]
	GetIntArrayRegion			[func-ptr!]
	GetLongArrayRegion			[func-ptr!]
	GetFloatArrayRegion			[func-ptr!]
	GetDoubleArrayRegion		[func-ptr!]

	SetBooleanArrayRegion		[func-ptr!]
	SetByteArrayRegion			[func-ptr!]
	SetCharArrayRegion			[func-ptr!]
	SetShortArrayRegion			[func-ptr!]
	SetIntArrayRegion			[func-ptr!]
	SetLongArrayRegion			[func-ptr!]
	SetFloatArrayRegion			[func-ptr!]
	SetDoubleArrayRegion		[func-ptr!]

	RegisterNatives				[func-ptr!]
	UnregisterNatives			[func-ptr!]
	MonitorEnter				[func-ptr!]
	MonitorExit					[func-ptr!]
	GetJavaVM					[func-ptr!]
	GetStringRegion				[func-ptr!]
	GetStringUTFRegion			[func-ptr!]
	GetPrimitiveArrayCritical	[func-ptr!]
	ReleasePrimitiveArrayCritical [func-ptr!]
	GetStringCritical			[func-ptr!]
	ReleaseStringCritical		[func-ptr!]
	NewWeakGlobalRef			[func-ptr!]
	DeleteWeakGlobalRef			[func-ptr!]
	ExceptionCheck				[function! [[JNICALL] env [JNI-ptr!] return: [logic!]]]
	NewDirectByteBuffer			[func-ptr!]
	GetDirectBufferAddress		[func-ptr!]
	GetDirectBufferCapacity		[func-ptr!]
	GetObjectRefType			[func-ptr!]
]

JNI-env!: alias JNI-ptr!

get-method: func [
	env		[JNI-env!]
	class	[jclass!]
	name	[c-string!]
	sig		[c-string!]
	return: [jmethodID!]
	/local
		id 	[jmethodID!]
][
	id: env/jni/GetMethodID env class name sig
	if null? id [print-line ["error: GetMethodID failed on " name sig]]
	id
]

get-static-method: func [
	env		[JNI-env!]
	class	[jclass!]
	name	[c-string!]
	sig		[c-string!]
	return: [jmethodID!]
	/local
		id 	[jmethodID!]
][
	id: env/jni/GetStaticMethodID env class name sig
	if null? id [print-line ["error: GetStaticMethodID failed on " name sig]]
	id
]

instantiate: func [
	[typed]
	count	[integer!]
	list	[typed-value!]
	return: [jobject!]
	/local
		env	  [JNI-env!]
		class [jclass!]
		id	  [jmethodID!]
		item  [typed-value!]
][
	env: as JNI-env! list/value
	list: list + 1
	class: as jclass! list/value
	list: list + 1
	id: get-method env class "<init>" as c-string! list/value
	list: list - 2

	while [count > 0][
		either count = 3 [
			push id										;-- replace sig by the constructor id
		][
			item: list + count - 1
			either item/type = type-c-string! [
				push env/jni/NewStringUTF env as c-string! item/value
			][
				push item/value
			]
		]
		count: count - 1
	]
	env/jni/NewObject 0									;@@ temporary change for Red bridge
	;env/jni/NewObject
]

JNI_OnLoad: func [
	vm 		 [int-ptr!]
	reserved [byte-ptr!]
	return:  [integer!]
][
	#if OS = 'Linux [***-dll-entry-point]				;@@ temporary workaround until ELF emitter handles it
	version-1.6
]

#export JNICALL [
	JNI_OnLoad
]

Red/System [
	Title:   "JVM bridge"
	Author:  "Nenad Rakocevic, Kaj de Vos"
	File: 	 %JNI.reds
	Tabs:	 4
	Rights:  "Copyright (C) 2013 Nenad Rakocevic, Kaj de Vos. All rights reserved."
	License: {
		Distributed under the Boost Software License, Version 1.0.
		See https://github.com/dockimbel/Red/blob/master/BSL-License.txt
	}
]

#define func-ptr!	integer!

#define jmethodID!	int-ptr!
#define jint!		integer!
#define jobject!	int-ptr!
#define jclass!		int-ptr!
#define jstring!	int-ptr!
#define jboolean!	int-ptr!

#define JNI-ptr!	[struct! [jni [JNI!]]]
#define JVM-ptr!	[struct! [ptr [JVM!]]]

#switch OS [
	Windows  [#define JNICALL stdcall]
	#default [#define JNICALL cdecl]
]

#define JNI_FALSE	#"^(00)"
#define JNI_TRUE  	#"^(01)"

#enum version! [
	version-1.1:	00010001h
	version-1.2:	00010002h
	version-1.4:	00010004h
	version-1.6:	00010006h
]

JVM!: alias struct! [
    reserved0					[int-ptr!]
    reserved1					[int-ptr!]
    reserved2					[int-ptr!]

    DestroyJavaVM 				[function! [[JNICALL] vm [JVM-ptr!] return: [jint!]]]
	AttachCurrentThread			[function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] args [byte-ptr!] return: [jint!]]]
	DetachCurrentThread 		[function! [[JNICALL] vm [JVM-ptr!] return: [jint!]]]
    GetEnv						[function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] version [integer!] return: [jint!]]]
    AttachCurrentThreadAsDaemon [function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] args [byte-ptr!] return: [jint!]]]
]

JNI!: alias struct! [
    reserved0					[int-ptr!]
    reserved1					[int-ptr!]
    reserved2					[int-ptr!]
    reserved3					[int-ptr!]

	GetVersion					[func-ptr!]
	DefineClass					[func-ptr!]
	FindClass					[function! [[JNICALL] env [JNI-ptr!] name [c-string!] return: [jclass!]]]
	FromReflectedMethod			[function! [[JNICALL] env [JNI-ptr!] method [jobject!] return: [jmethodID!]]]
	FromReflectedField			[func-ptr!]
	ToReflectedMethod			[func-ptr!]
	GetSuperclass				[func-ptr!]
	IsAssignableFrom			[func-ptr!]
	ToReflectedField			[func-ptr!]

	Throw						[func-ptr!]
	ThrowNew					[func-ptr!]
	ExceptionOccurred			[func-ptr!]
	ExceptionDescribe			[func-ptr!]
	ExceptionClear				[func-ptr!]
	FatalError					[func-ptr!]

	PushLocalFrame				[func-ptr!]
	PopLocalFrame				[func-ptr!]

	NewGlobalRef				[function! [[JNICALL] env [JNI-ptr!] obj [jobject!] return: [jobject!]]]
	DeleteGlobalRef				[function! [[JNICALL] env [JNI-ptr!] ref [jobject!]]]
	DeleteLocalRef				[function! [[JNICALL] env [JNI-ptr!] obj [jobject!]]]
	IsSameObject				[func-ptr!]
	NewLocalRef					[func-ptr!]
	EnsureLocalCapacity			[func-ptr!]

	AllocObject					[func-ptr!]
	NewObject					[function! [[JNICALL] return: [jobject!]]] ;-- stack frame is manually constructed
	NewObjectV					[func-ptr!]
	NewObjectA					[func-ptr!]

	GetObjectClass				[function! [[JNICALL] env [JNI-ptr!] obj [jobject!] return: [jclass!]]]
	IsInstanceOf				[func-ptr!]
	GetMethodID					[function! [[JNICALL] env [JNI-ptr!] class [jclass!] name [c-string!] sig [c-string!] return: [jmethodID!]]]

	CallObjectMethod			[function! [[JNICALL variadic] return: [jobject!]]]
	CallObjectMethodV			[func-ptr!]
	CallObjectMethodA			[func-ptr!]

	CallBooleanMethod			[func-ptr!]
	CallBooleanMethodV			[func-ptr!]
	CallBooleanMethodA			[func-ptr!]

	CallByteMethod				[func-ptr!]
	CallByteMethodV				[func-ptr!]
	CallByteMethodA				[func-ptr!]

	CallCharMethod				[func-ptr!]
	CallCharMethodV				[func-ptr!]
	CallCharMethodA				[func-ptr!]

	CallShortMethod				[func-ptr!]
	CallShortMethodV			[func-ptr!]
	CallShortMethodA			[func-ptr!]

	CallIntMethod				[func-ptr!]
	CallIntMethodV				[func-ptr!]
	CallIntMethodA				[func-ptr!]

	CallLongMethod				[func-ptr!]
	CallLongMethodV				[func-ptr!]
	CallLongMethodA				[func-ptr!]

	CallFloatMethod				[func-ptr!]
	CallFloatMethodV			[func-ptr!]
	CallFloatMethodA			[func-ptr!]

	CallDoubleMethod			[func-ptr!]
	CallDoubleMethodV			[func-ptr!]
	CallDoubleMethodA			[func-ptr!]

	CallVoidMethod				[func-ptr!]
	CallVoidMethodV				[func-ptr!]
	CallVoidMethodA				[func-ptr!]

	CallNonvirtualObjectMethod	[func-ptr!]
	CallNonvirtualObjectMethodV	[func-ptr!]
	CallNonvirtualObjectMethodA	[func-ptr!]

	CallNonvirtualBooleanMethod	 [func-ptr!]
	CallNonvirtualBooleanMethodV [func-ptr!]
	CallNonvirtualBooleanMethodA [func-ptr!]

	CallNonvirtualByteMethod	[func-ptr!]
	CallNonvirtualByteMethodV	[func-ptr!]
	CallNonvirtualByteMethodA	[func-ptr!]

	CallNonvirtualCharMethod	[func-ptr!]
	CallNonvirtualCharMethodV	[func-ptr!]
	CallNonvirtualCharMethodA	[func-ptr!]

	CallNonvirtualShortMethod	[func-ptr!]
	CallNonvirtualShortMethodV	[func-ptr!]
	CallNonvirtualShortMethodA	[func-ptr!]

	CallNonvirtualIntMethod		[func-ptr!]
	CallNonvirtualIntMethodV	[func-ptr!]
	CallNonvirtualIntMethodA	[func-ptr!]

	CallNonvirtualLongMethod	[func-ptr!]
	CallNonvirtualLongMethodV	[func-ptr!]
	CallNonvirtualLongMethodA	[func-ptr!]

	CallNonvirtualFloatMethod	[func-ptr!]
	CallNonvirtualFloatMethodV	[func-ptr!]
	CallNonvirtualFloatMethodA	[func-ptr!]

	CallNonvirtualDoubleMethod	[func-ptr!]
	CallNonvirtualDoubleMethodV	[func-ptr!]
	CallNonvirtualDoubleMethodA	[func-ptr!]

	CallNonvirtualVoidMethod	[func-ptr!]
	CallNonvirtualVoidMethodV	[func-ptr!]
	CallNonvirtualVoidMethodA	[func-ptr!]

	GetFieldID					[func-ptr!]
	GetObjectField				[func-ptr!]
	GetBooleanField				[func-ptr!]
	GetByteField				[func-ptr!]
	GetCharField				[func-ptr!]
	GetShortField				[func-ptr!]
	GetIntField					[func-ptr!]
	GetLongField				[func-ptr!]
	GetFloatField				[func-ptr!]
	GetDoubleField				[func-ptr!]

	SetObjectField				[func-ptr!]
	SetBooleanField				[func-ptr!]
	SetByteField				[func-ptr!]
	SetCharField				[func-ptr!]
	SetShortField				[func-ptr!]
	SetIntField					[func-ptr!]
	SetLongField				[func-ptr!]
	SetFloatField				[func-ptr!]
	SetDoubleField				[func-ptr!]

	GetStaticMethodID			[function! [[JNICALL] env [JNI-ptr!] class [jclass!] name [c-string!] sig [c-string!] return: [jmethodID!]]]

	CallStaticObjectMethod		[function! [[JNICALL variadic] return: [jobject!]]]
	CallStaticObjectMethodV		[func-ptr!]
	CallStaticObjectMethodA		[func-ptr!]

	CallStaticBooleanMethod		[func-ptr!]
	CallStaticBooleanMethodV	[func-ptr!]
	CallStaticBooleanMethodA	[func-ptr!]

	CallStaticByteMethod		[func-ptr!]
	CallStaticByteMethodV		[func-ptr!]
	CallStaticByteMethodA		[func-ptr!]

	CallStaticCharMethod		[func-ptr!]
	CallStaticCharMethodV		[func-ptr!]
	CallStaticCharMethodA		[func-ptr!]

	CallStaticShortMethod		[func-ptr!]
	CallStaticShortMethodV		[func-ptr!]
	CallStaticShortMethodA		[func-ptr!]

	CallStaticIntMethod			[func-ptr!]
	CallStaticIntMethodV		[func-ptr!]
	CallStaticIntMethodA		[func-ptr!]

	CallStaticLongMethod		[func-ptr!]
	CallStaticLongMethodV		[func-ptr!]
	CallStaticLongMethodA		[func-ptr!]

	CallStaticFloatMethod		[func-ptr!]
	CallStaticFloatMethodV		[func-ptr!]
	CallStaticFloatMethodA		[func-ptr!]

	CallStaticDoubleMethod		[func-ptr!]
	CallStaticDoubleMethodV		[func-ptr!]
	CallStaticDoubleMethodA		[func-ptr!]

	CallStaticVoidMethod		[func-ptr!]
	CallStaticVoidMethodV		[func-ptr!]
	CallStaticVoidMethodA		[func-ptr!]

	GetStaticFieldID			[func-ptr!]
	GetStaticObjectField		[func-ptr!]
	GetStaticBooleanField		[func-ptr!]
	GetStaticByteField			[func-ptr!]
	GetStaticCharField			[func-ptr!]
	GetStaticShortField			[func-ptr!]
	GetStaticIntField			[func-ptr!]
	GetStaticLongField			[func-ptr!]
	GetStaticFloatField			[func-ptr!]
	GetStaticDoubleField		[func-ptr!]

	SetStaticObjectField		[func-ptr!]
	SetStaticBooleanField		[func-ptr!]
	SetStaticByteField			[func-ptr!]
	SetStaticCharField			[func-ptr!]
	SetStaticShortField			[func-ptr!]
	SetStaticIntField			[func-ptr!]
	SetStaticLongField			[func-ptr!]
	SetStaticFloatField			[func-ptr!]
	SetStaticDoubleField		[func-ptr!]

	NewString					[func-ptr!]
	GetStringLength				[func-ptr!]
	GetStringChars				[func-ptr!]
	ReleaseStringChars			[func-ptr!]

	NewStringUTF				[function! [[JNICALL] env [JNI-ptr!] bytes [c-string!] return: [jobject!]]]
	GetStringUTFLength			[func-ptr!]
	GetStringUTFChars			[function! [[JNICALL] env [JNI-ptr!] str [jstring!] isCopy [struct! [c [jboolean!]]] return: [c-string!]]]
	ReleaseStringUTFChars		[function! [[JNICALL] env [JNI-ptr!] str [jstring!] buf [c-string!]]]

	GetArrayLength				[function! [[JNICALL] env [JNI-ptr!] array [jobject!] return: [jint!]]]
	NewObjectArray				[func-ptr!]
	GetObjectArrayElement		[function! [[JNICALL] env [JNI-ptr!] array [jobject!] idx [jint!] return: [jobject!]]]
	SetObjectArrayElement		[func-ptr!]
	;...
]

JNI-env!: alias JNI-ptr!

get-method: func [
	env		[JNI-env!]
	class	[jclass!]
	name	[c-string!]
	sig		[c-string!]
	return: [jmethodID!]
	/local
		id 	[jmethodID!]
][
	id: env/jni/GetMethodID env class name sig
	if null? id [print-line ["error: GetMethodID failed on " name sig]]
	id
]

get-static-method: func [
	env		[JNI-env!]
	class	[jclass!]
	name	[c-string!]
	sig		[c-string!]
	return: [jmethodID!]
	/local
		id 	[jmethodID!]
][
	id: env/jni/GetStaticMethodID env class name sig
	if null? id [print-line ["error: GetStaticMethodID failed on " name sig]]
	id
]

instantiate: func [
	[typed]
	count	[integer!]
	list	[typed-value!]
	return: [jobject!]
	/local
		env	  [JNI-env!]
		class [jclass!]
		id	  [jmethodID!]
		item  [typed-value!]
][
	env: as JNI-env! list/value
	list: list + 1
	class: as jclass! list/value
	list: list + 1
	id: get-method env class "<init>" as c-string! list/value
	list: list - 2

	while [count > 0][
		either count = 3 [
			push id										;-- replace sig by the constructor id
		][
			item: list + count - 1
			either item/type = type-c-string! [
				push env/jni/NewStringUTF env as c-string! item/value
			][
				push item/value
			]
		]
		count: count - 1
	]
	env/jni/NewObject
]

JNI_OnLoad: func [
	vm 		 [int-ptr!]
	reserved [byte-ptr!]
	return:  [integer!]
][
	#if OS = 'Linux [***-dll-entry-point]				;@@ temporary workaround until ELF emitter handles it
	version-1.6
]

#export JNICALL [
	JNI_OnLoad
]