conjure-js 0.0.12 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist-cli/conjure-js.mjs +9360 -5298
  2. package/dist-vite-plugin/index.mjs +9463 -5185
  3. package/package.json +3 -1
  4. package/src/bin/cli.ts +2 -2
  5. package/src/bin/nrepl-symbol.ts +150 -0
  6. package/src/bin/nrepl.ts +289 -167
  7. package/src/bin/version.ts +1 -1
  8. package/src/clojure/core.clj +757 -29
  9. package/src/clojure/core.clj.d.ts +75 -131
  10. package/src/clojure/generated/builtin-namespace-registry.ts +4 -0
  11. package/src/clojure/generated/clojure-core-source.ts +758 -29
  12. package/src/clojure/generated/clojure-set-source.ts +136 -0
  13. package/src/clojure/generated/clojure-walk-source.ts +72 -0
  14. package/src/clojure/set.clj +132 -0
  15. package/src/clojure/set.clj.d.ts +20 -0
  16. package/src/clojure/string.clj.d.ts +14 -0
  17. package/src/clojure/walk.clj +68 -0
  18. package/src/clojure/walk.clj.d.ts +7 -0
  19. package/src/core/assertions.ts +114 -6
  20. package/src/core/bootstrap.ts +337 -0
  21. package/src/core/conversions.ts +48 -31
  22. package/src/core/core-module.ts +303 -0
  23. package/src/core/env.ts +20 -6
  24. package/src/core/evaluator/apply.ts +40 -25
  25. package/src/core/evaluator/arity.ts +8 -8
  26. package/src/core/evaluator/async-evaluator.ts +565 -0
  27. package/src/core/evaluator/collections.ts +28 -5
  28. package/src/core/evaluator/destructure.ts +180 -69
  29. package/src/core/evaluator/dispatch.ts +12 -14
  30. package/src/core/evaluator/evaluate.ts +22 -20
  31. package/src/core/evaluator/expand.ts +45 -15
  32. package/src/core/evaluator/form-parsers.ts +178 -0
  33. package/src/core/evaluator/index.ts +7 -9
  34. package/src/core/evaluator/js-interop.ts +189 -0
  35. package/src/core/evaluator/quasiquote.ts +14 -8
  36. package/src/core/evaluator/recur-check.ts +6 -6
  37. package/src/core/evaluator/special-forms.ts +234 -191
  38. package/src/core/factories.ts +182 -3
  39. package/src/core/index.ts +54 -4
  40. package/src/core/module.ts +136 -0
  41. package/src/core/ns-forms.ts +107 -0
  42. package/src/core/printer.ts +371 -11
  43. package/src/core/reader.ts +84 -33
  44. package/src/core/registry.ts +209 -0
  45. package/src/core/runtime.ts +376 -0
  46. package/src/core/session.ts +253 -487
  47. package/src/core/stdlib/arithmetic.ts +528 -194
  48. package/src/core/stdlib/async-fns.ts +132 -0
  49. package/src/core/stdlib/atoms.ts +291 -56
  50. package/src/core/stdlib/errors.ts +54 -50
  51. package/src/core/stdlib/hof.ts +82 -166
  52. package/src/core/stdlib/js-namespace.ts +344 -0
  53. package/src/core/stdlib/lazy.ts +34 -0
  54. package/src/core/stdlib/maps-sets.ts +322 -0
  55. package/src/core/stdlib/meta.ts +61 -30
  56. package/src/core/stdlib/predicates.ts +325 -187
  57. package/src/core/stdlib/regex.ts +126 -98
  58. package/src/core/stdlib/seq.ts +564 -0
  59. package/src/core/stdlib/strings.ts +164 -135
  60. package/src/core/stdlib/transducers.ts +95 -100
  61. package/src/core/stdlib/utils.ts +292 -130
  62. package/src/core/stdlib/vars.ts +27 -27
  63. package/src/core/stdlib/vectors.ts +122 -0
  64. package/src/core/tokenizer.ts +2 -2
  65. package/src/core/transformations.ts +117 -9
  66. package/src/core/types.ts +98 -2
  67. package/src/host/node-host-module.ts +74 -0
  68. package/src/{vite-plugin-clj/nrepl-relay.ts → nrepl/relay.ts} +72 -11
  69. package/src/vite-plugin-clj/codegen.ts +87 -95
  70. package/src/vite-plugin-clj/index.ts +178 -23
  71. package/src/vite-plugin-clj/namespace-utils.ts +39 -0
  72. package/src/vite-plugin-clj/static-analysis.ts +211 -0
  73. package/src/clojure/demo.clj +0 -72
  74. package/src/clojure/demo.clj.d.ts +0 -0
  75. package/src/core/core-env.ts +0 -61
  76. package/src/core/stdlib/collections.ts +0 -739
  77. package/src/host/node.ts +0 -55
@@ -0,0 +1,211 @@
1
+ import { isList, isSymbol, isVector } from '../core/assertions'
2
+ import { readForms } from '../core/reader'
3
+ import { tokenize } from '../core/tokenizer'
4
+ import type { Arity, CljList, CljMap, CljValue, DestructurePattern } from '../core/types'
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Public types
8
+ // ---------------------------------------------------------------------------
9
+
10
+ export interface VarDescriptor {
11
+ name: string
12
+ kind: 'fn' | 'const' | 'unknown'
13
+ arities?: Arity[] // present when kind === 'fn'
14
+ tsType?: string // present when kind === 'const' and value type is inferrable
15
+ isPrivate: boolean
16
+ isMacro: boolean
17
+ }
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Public API
21
+ // ---------------------------------------------------------------------------
22
+
23
+ /**
24
+ * Parse Clojure source and return descriptors for all top-level var definitions.
25
+ * Pure function — no session, no execution, no side effects.
26
+ *
27
+ * Handles: defn, defn-, defmacro, def, defonce, declare.
28
+ * Skips: ns, and any other top-level form that is not a definition.
29
+ *
30
+ * Private vars (defn-) are included with isPrivate: true so callers can decide
31
+ * whether to export them or not.
32
+ */
33
+ export function readNamespaceVars(source: string): VarDescriptor[] {
34
+ const forms = readForms(tokenize(source))
35
+ const descriptors: VarDescriptor[] = []
36
+
37
+ for (const form of forms) {
38
+ if (!isList(form) || form.value.length < 2) continue
39
+ const head = form.value[0]
40
+ if (!isSymbol(head)) continue
41
+
42
+ const descriptor = parseTopLevelDef(form, head.name)
43
+ if (descriptor) descriptors.push(descriptor)
44
+ }
45
+
46
+ return descriptors
47
+ }
48
+
49
+ // ---------------------------------------------------------------------------
50
+ // Metadata helpers
51
+ // ---------------------------------------------------------------------------
52
+
53
+ function hasPrivateMeta(meta: CljMap | undefined): boolean {
54
+ return (meta?.entries ?? []).some(
55
+ ([k, val]) =>
56
+ k.kind === 'keyword' && k.name === ':private' &&
57
+ val.kind === 'boolean' && val.value === true
58
+ )
59
+ }
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Per-form dispatch
63
+ // ---------------------------------------------------------------------------
64
+
65
+ function parseTopLevelDef(form: CljList, op: string): VarDescriptor | null {
66
+ switch (op) {
67
+ case 'defn':
68
+ return parseDefn(form, false, false)
69
+ case 'defn-':
70
+ return parseDefn(form, true, false)
71
+ case 'defmacro':
72
+ return parseDefn(form, false, true)
73
+ case 'def':
74
+ case 'defonce':
75
+ return parseDef(form)
76
+ case 'declare':
77
+ return parseDeclare(form)
78
+ default:
79
+ return null
80
+ }
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // defn / defn- / defmacro
85
+ // ---------------------------------------------------------------------------
86
+
87
+ function parseDefn(form: CljList, isPrivate: boolean, isMacro: boolean): VarDescriptor | null {
88
+ const nameSym = form.value[1]
89
+ if (!isSymbol(nameSym)) return null
90
+
91
+ const private_ = isPrivate || hasPrivateMeta(nameSym.meta)
92
+
93
+ // Elements after the name: optional docstring, then params or arity clauses
94
+ const rest = form.value.slice(2)
95
+ // Skip optional docstring
96
+ const start = rest.length > 0 && rest[0].kind === 'string' ? 1 : 0
97
+ const bodyForms = rest.slice(start)
98
+
99
+ if (bodyForms.length === 0) {
100
+ // Bare defn with no param list — treat as unknown function
101
+ return { name: nameSym.name, kind: 'fn', arities: [], isPrivate: private_, isMacro }
102
+ }
103
+
104
+ const arities: Arity[] = isList(bodyForms[0])
105
+ ? // Multi-arity: each clause is a list whose first element is the params vector
106
+ bodyForms.filter(isList).map(parseArityClause)
107
+ : // Single-arity: bodyForms[0] is the params vector
108
+ isVector(bodyForms[0]) ? [vectorToArity(bodyForms[0])] : []
109
+
110
+ return { name: nameSym.name, kind: 'fn', arities, isPrivate: private_, isMacro }
111
+ }
112
+
113
+ function parseArityClause(clause: CljList): Arity {
114
+ const paramVec = clause.value[0]
115
+ return isVector(paramVec) ? vectorToArity(paramVec) : { params: [], restParam: null, body: [] }
116
+ }
117
+
118
+ function vectorToArity(paramVec: { value: CljValue[] }): Arity {
119
+ const params: DestructurePattern[] = []
120
+ let restParam: DestructurePattern | null = null
121
+
122
+ for (let i = 0; i < paramVec.value.length; i++) {
123
+ const p = paramVec.value[i]
124
+ if (isSymbol(p) && p.name === '&') {
125
+ const next = paramVec.value[i + 1]
126
+ if (next) restParam = next as DestructurePattern
127
+ break
128
+ }
129
+ params.push(p as DestructurePattern)
130
+ }
131
+
132
+ return { params, restParam, body: [] }
133
+ }
134
+
135
+ // ---------------------------------------------------------------------------
136
+ // def / defonce
137
+ // ---------------------------------------------------------------------------
138
+
139
+ function parseDef(form: CljList): VarDescriptor | null {
140
+ const nameSym = form.value[1]
141
+ if (!isSymbol(nameSym)) return null
142
+
143
+ const isPrivate = hasPrivateMeta(nameSym.meta)
144
+ const value = form.value[2] // may be undefined for bare (def name)
145
+
146
+ if (!value) {
147
+ return { name: nameSym.name, kind: 'unknown', isPrivate, isMacro: false }
148
+ }
149
+
150
+ // Inline function literal
151
+ const fnArities = tryExtractFnArities(value)
152
+ if (fnArities !== null) {
153
+ return { name: nameSym.name, kind: 'fn', arities: fnArities, isPrivate, isMacro: false }
154
+ }
155
+
156
+ // Literal values with inferrable TypeScript types
157
+ const tsType = inferLiteralTsType(value)
158
+ if (tsType !== null) {
159
+ return { name: nameSym.name, kind: 'const', tsType, isPrivate, isMacro: false }
160
+ }
161
+
162
+ return { name: nameSym.name, kind: 'unknown', isPrivate, isMacro: false }
163
+ }
164
+
165
+ function inferLiteralTsType(value: CljValue): string | null {
166
+ switch (value.kind) {
167
+ case 'number': return 'number'
168
+ case 'string': return 'string'
169
+ case 'boolean': return 'boolean'
170
+ case 'nil': return 'null'
171
+ case 'keyword': return 'string'
172
+ case 'vector':
173
+ case 'set': return 'unknown[]'
174
+ case 'map': return 'Record<string, unknown>'
175
+ default: return null
176
+ }
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // declare
181
+ // ---------------------------------------------------------------------------
182
+
183
+ function parseDeclare(form: CljList): VarDescriptor | null {
184
+ const nameSym = form.value[1]
185
+ if (!isSymbol(nameSym)) return null
186
+ return { name: nameSym.name, kind: 'unknown', isPrivate: false, isMacro: false }
187
+ }
188
+
189
+ // ---------------------------------------------------------------------------
190
+ // (fn ...) extraction for def with inline function
191
+ // ---------------------------------------------------------------------------
192
+
193
+ function tryExtractFnArities(value: CljValue): Arity[] | null {
194
+ if (!isList(value)) return null
195
+ const head = value.value[0]
196
+ if (!isSymbol(head) || head.name !== 'fn') return null
197
+
198
+ // After fn: optional name symbol, then params-vector or arity-clauses
199
+ let rest = value.value.slice(1)
200
+ if (rest.length > 0 && isSymbol(rest[0])) rest = rest.slice(1) // skip optional fn name
201
+
202
+ if (rest.length === 0) return []
203
+
204
+ if (isVector(rest[0])) {
205
+ // Single arity: (fn [params] body)
206
+ return [vectorToArity(rest[0])]
207
+ }
208
+
209
+ // Multi arity: (fn ([params] body) ([params] body))
210
+ return rest.filter(isList).map(parseArityClause)
211
+ }
@@ -1,72 +0,0 @@
1
- (ns demo
2
- (:require [demo.math :refer [pi square factorial] :as m]))
3
-
4
- (def greeting "Hello from Clojure!")
5
-
6
-
7
- greeting
8
- (def add m/add)
9
-
10
- pi
11
-
12
- (add 1 2)
13
-
14
- (square 3)
15
-
16
- (def x 42)
17
-
18
- (doc -)
19
-
20
- (var? #'x)
21
-
22
- #'x
23
-
24
- (+ 1 2)
25
-
26
- pi
27
-
28
- (slurp "test.txt")
29
- (spit "test.txt" "hello from the runtime brooo")
30
-
31
- (doc reduce)
32
-
33
- (defn greet [name]
34
- (str greeting " Welcome, " name "!"))
35
-
36
- (greet "Regibyte")
37
-
38
- (defn fibonacci
39
- "This is the fibonacci function"
40
- [n]
41
- (loop [i 0 a 0 b 1]
42
- (if (= i n)
43
- a
44
- (recur (inc i) b (+ a b)))))
45
-
46
- (map fibonacci [1 2 3 4 5 6])
47
-
48
- m/factorial
49
-
50
- (m/factorial 5)
51
- (m/factorial 10)
52
-
53
- (+ 1
54
- (/ 1 0))
55
-
56
- (meta m/factorial)
57
-
58
-
59
- (+ 1 2)
60
-
61
- (println "Hello World!" "From Calva!!!!!!")
62
-
63
- (type {:this-is :awesome!})
64
-
65
- (when true
66
- (println "Yes\n")
67
- (println "This\n")
68
- (println "Is working!")
69
- 42)
70
-
71
-
72
- (map inc [2 3 4 5 8 2])
File without changes
@@ -1,61 +0,0 @@
1
- import { internVar, makeEnv, makeNamespace } from './env'
2
- import { cljNativeFunction, cljNil } from './factories'
3
- import { arithmeticFunctions } from './stdlib/arithmetic'
4
- import { atomFunctions } from './stdlib/atoms'
5
- import { collectionFunctions } from './stdlib/collections'
6
- import { errorFunctions } from './stdlib/errors'
7
- import { hofFunctions } from './stdlib/hof'
8
- import { metaFunctions } from './stdlib/meta'
9
- import { predicateFunctions } from './stdlib/predicates'
10
- import { regexFunctions } from './stdlib/regex'
11
- import { stringFunctions } from './stdlib/strings'
12
- import { transducerFunctions } from './stdlib/transducers'
13
- import { utilFunctions } from './stdlib/utils'
14
- import { varFunctions } from './stdlib/vars'
15
- import { valueToString } from './transformations'
16
- import { type CljValue, type Env } from './types'
17
-
18
- const nativeFunctions = {
19
- ...arithmeticFunctions,
20
- ...atomFunctions,
21
- ...collectionFunctions,
22
- ...errorFunctions,
23
- ...predicateFunctions,
24
- ...hofFunctions,
25
- ...metaFunctions,
26
- ...transducerFunctions,
27
- ...regexFunctions,
28
- ...stringFunctions,
29
- ...utilFunctions,
30
- ...varFunctions,
31
- }
32
-
33
- export function loadCoreFunctions(env: Env, output?: (text: string) => void) {
34
- for (const [key, value] of Object.entries(nativeFunctions)) {
35
- internVar(key, value, env)
36
- }
37
- const emit = output ?? ((text: string) => console.log(text))
38
- internVar(
39
- 'println',
40
- cljNativeFunction('println', (...args: CljValue[]) => {
41
- emit(args.map(valueToString).join(' '))
42
- return cljNil()
43
- }),
44
- env
45
- )
46
- internVar(
47
- 'print',
48
- cljNativeFunction('print', (...args: CljValue[]) => {
49
- emit(args.map(valueToString).join(' '))
50
- return cljNil()
51
- }),
52
- env
53
- )
54
- }
55
-
56
- export function makeCoreEnv(output?: (text: string) => void): Env {
57
- const env = makeEnv()
58
- env.ns = makeNamespace('clojure.core')
59
- loadCoreFunctions(env, output)
60
- return env
61
- }