feat: add mutable array compatibility primitives
cfb27b8 parent: 5757588 modified
src/core.nim +24 -1 | @@ -1,5 +1,5 @@ | ||
| 1 | 1 | ## clonim core — clojure.core builtins, registered into the global var table. |
| 2 | -import std/[strutils, math, times, random, re, os, httpclient] | |
| 2 | +import std/[strutils, math, times, random, re, os, httpclient, sequtils] | |
| 3 | 3 | import runtime |
| 4 | 4 | |
| 5 | 5 | proc num(v: Value): float64 = |
| @@ -544,6 +544,29 @@ proc registerCore*() = | ||
| 544 | 544 | def "slurp", proc (a: openArray[Value]): Value = mkStr(readFile(a[0].s)) |
| 545 | 545 | def "spit", proc (a: openArray[Value]): Value = |
| 546 | 546 | writeFile(a[0].s, str(a[1])); NilV |
| 547 | + def "int-array", proc (a: openArray[Value]): Value = | |
| 548 | + if a.len == 1 and a[0].kind == kInt: mkList(newSeqWith(int(a[0].i), mkInt(0))) | |
| 549 | + elif a.len == 1: mkList(toSeq(a[0])) else: mkList(a) | |
| 550 | + def "long-array", proc (a: openArray[Value]): Value = | |
| 551 | + if a.len == 1 and a[0].kind == kInt: mkList(newSeqWith(int(a[0].i), mkInt(0))) | |
| 552 | + elif a.len == 1: mkList(toSeq(a[0])) else: mkList(a) | |
| 553 | + def "byte-array", proc (a: openArray[Value]): Value = | |
| 554 | + if a.len == 1: mkList(toSeq(a[0])) else: mkList(a) | |
| 555 | + def "alength", proc (a: openArray[Value]): Value = mkInt(count(a[0])) | |
| 556 | + def "aget", proc (a: openArray[Value]): Value = | |
| 557 | + let i = int(intOf(a[1])) | |
| 558 | + if a[0].kind == kList: a[0].obj.xs[i] else: toSeq(a[0])[i] | |
| 559 | + def "aset", proc (a: openArray[Value]): Value = | |
| 560 | + if a[0].kind != kList: err("aset expects an array") | |
| 561 | + a[0].obj.xs[int(intOf(a[1]))] = a[2]; a[2] | |
| 562 | + def "System/arraycopy", proc (a: openArray[Value]): Value = | |
| 563 | + for i in 0 ..< int(intOf(a[4])): | |
| 564 | + a[2].obj.xs[int(intOf(a[3])) + i] = a[0].obj.xs[int(intOf(a[1])) + i] | |
| 565 | + NilV | |
| 566 | + def ".getBytes", proc (a: openArray[Value]): Value = | |
| 567 | + var xs: seq[Value] = @[] | |
| 568 | + for ch in a[0].s: xs.add mkInt(ord(ch)) | |
| 569 | + mkList(xs) | |
| 547 | 570 | def "*delete-file*", proc (a: openArray[Value]): Value = |
| 548 | 571 | try: |
| 549 | 572 | removeFile(a[0].s) |
| @@ -1,5 +1,5 @@ | |||
| 1 | ## clonim core — clojure.core builtins, registered into the global var table. | 1 | ## clonim core — clojure.core builtins, registered into the global var table. |
| 2 | -import std/[strutils, math, times, random, re, os, httpclient] | 2 | +import std/[strutils, math, times, random, re, os, httpclient, sequtils] |
| 3 | import runtime | 3 | import runtime |
| 4 | 4 | ||
| 5 | proc num(v: Value): float64 = | 5 | proc num(v: Value): float64 = |
| @@ -544,6 +544,29 @@ proc registerCore*() = | |||
| 544 | def "slurp", proc (a: openArray[Value]): Value = mkStr(readFile(a[0].s)) | 544 | def "slurp", proc (a: openArray[Value]): Value = mkStr(readFile(a[0].s)) |
| 545 | def "spit", proc (a: openArray[Value]): Value = | 545 | def "spit", proc (a: openArray[Value]): Value = |
| 546 | writeFile(a[0].s, str(a[1])); NilV | 546 | writeFile(a[0].s, str(a[1])); NilV |
| 547 | + def "int-array", proc (a: openArray[Value]): Value = | ||
| 548 | + if a.len == 1 and a[0].kind == kInt: mkList(newSeqWith(int(a[0].i), mkInt(0))) | ||
| 549 | + elif a.len == 1: mkList(toSeq(a[0])) else: mkList(a) | ||
| 550 | + def "long-array", proc (a: openArray[Value]): Value = | ||
| 551 | + if a.len == 1 and a[0].kind == kInt: mkList(newSeqWith(int(a[0].i), mkInt(0))) | ||
| 552 | + elif a.len == 1: mkList(toSeq(a[0])) else: mkList(a) | ||
| 553 | + def "byte-array", proc (a: openArray[Value]): Value = | ||
| 554 | + if a.len == 1: mkList(toSeq(a[0])) else: mkList(a) | ||
| 555 | + def "alength", proc (a: openArray[Value]): Value = mkInt(count(a[0])) | ||
| 556 | + def "aget", proc (a: openArray[Value]): Value = | ||
| 557 | + let i = int(intOf(a[1])) | ||
| 558 | + if a[0].kind == kList: a[0].obj.xs[i] else: toSeq(a[0])[i] | ||
| 559 | + def "aset", proc (a: openArray[Value]): Value = | ||
| 560 | + if a[0].kind != kList: err("aset expects an array") | ||
| 561 | + a[0].obj.xs[int(intOf(a[1]))] = a[2]; a[2] | ||
| 562 | + def "System/arraycopy", proc (a: openArray[Value]): Value = | ||
| 563 | + for i in 0 ..< int(intOf(a[4])): | ||
| 564 | + a[2].obj.xs[int(intOf(a[3])) + i] = a[0].obj.xs[int(intOf(a[1])) + i] | ||
| 565 | + NilV | ||
| 566 | + def ".getBytes", proc (a: openArray[Value]): Value = | ||
| 567 | + var xs: seq[Value] = @[] | ||
| 568 | + for ch in a[0].s: xs.add mkInt(ord(ch)) | ||
| 569 | + mkList(xs) | ||
| 547 | def "*delete-file*", proc (a: openArray[Value]): Value = | 570 | def "*delete-file*", proc (a: openArray[Value]): Value = |
| 548 | try: | 571 | try: |
| 549 | removeFile(a[0].s) | 572 | removeFile(a[0].s) |
modified
src/namespaces.nim +2 -1 | @@ -99,9 +99,10 @@ proc checkVar(r: Resolver, ns: Namespace, target, name: string, | ||
| 99 | 99 | if target == "clojure.core": |
| 100 | 100 | if name in r.cores or (allowSyntax and name in syntaxHeads): return |
| 101 | 101 | fail("no definition " & canonical) |
| 102 | + # JVM-style host calls (for example System/arraycopy) are globally provided. | |
| 103 | + if canonical in r.hosts: return | |
| 102 | 104 | if target != ns.name and target notin ns.required: |
| 103 | 105 | fail("namespace " & target & " is not required by " & ns.name) |
| 104 | - if canonical in r.hosts: return | |
| 105 | 106 | if not r.spaces.hasKey(target) or name notin r.spaces[target].defs: |
| 106 | 107 | fail("no definition " & canonical) |
| 107 | 108 | if target != ns.name and name in r.spaces[target].privateDefs: |
| @@ -99,9 +99,10 @@ proc checkVar(r: Resolver, ns: Namespace, target, name: string, | |||
| 99 | if target == "clojure.core": | 99 | if target == "clojure.core": |
| 100 | if name in r.cores or (allowSyntax and name in syntaxHeads): return | 100 | if name in r.cores or (allowSyntax and name in syntaxHeads): return |
| 101 | fail("no definition " & canonical) | 101 | fail("no definition " & canonical) |
| 102 | + # JVM-style host calls (for example System/arraycopy) are globally provided. | ||
| 103 | + if canonical in r.hosts: return | ||
| 102 | if target != ns.name and target notin ns.required: | 104 | if target != ns.name and target notin ns.required: |
| 103 | fail("namespace " & target & " is not required by " & ns.name) | 105 | fail("namespace " & target & " is not required by " & ns.name) |
| 104 | - if canonical in r.hosts: return | ||
| 105 | if not r.spaces.hasKey(target) or name notin r.spaces[target].defs: | 106 | if not r.spaces.hasKey(target) or name notin r.spaces[target].defs: |
| 106 | fail("no definition " & canonical) | 107 | fail("no definition " & canonical) |
| 107 | if target != ns.name and name in r.spaces[target].privateDefs: | 108 | if target != ns.name and name in r.spaces[target].privateDefs: |