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.
- package/dist-cli/conjure-js.mjs +9360 -5298
- package/dist-vite-plugin/index.mjs +9463 -5185
- package/package.json +3 -1
- package/src/bin/cli.ts +2 -2
- package/src/bin/nrepl-symbol.ts +150 -0
- package/src/bin/nrepl.ts +289 -167
- package/src/bin/version.ts +1 -1
- package/src/clojure/core.clj +757 -29
- package/src/clojure/core.clj.d.ts +75 -131
- package/src/clojure/generated/builtin-namespace-registry.ts +4 -0
- package/src/clojure/generated/clojure-core-source.ts +758 -29
- package/src/clojure/generated/clojure-set-source.ts +136 -0
- package/src/clojure/generated/clojure-walk-source.ts +72 -0
- package/src/clojure/set.clj +132 -0
- package/src/clojure/set.clj.d.ts +20 -0
- package/src/clojure/string.clj.d.ts +14 -0
- package/src/clojure/walk.clj +68 -0
- package/src/clojure/walk.clj.d.ts +7 -0
- package/src/core/assertions.ts +114 -6
- package/src/core/bootstrap.ts +337 -0
- package/src/core/conversions.ts +48 -31
- package/src/core/core-module.ts +303 -0
- package/src/core/env.ts +20 -6
- package/src/core/evaluator/apply.ts +40 -25
- package/src/core/evaluator/arity.ts +8 -8
- package/src/core/evaluator/async-evaluator.ts +565 -0
- package/src/core/evaluator/collections.ts +28 -5
- package/src/core/evaluator/destructure.ts +180 -69
- package/src/core/evaluator/dispatch.ts +12 -14
- package/src/core/evaluator/evaluate.ts +22 -20
- package/src/core/evaluator/expand.ts +45 -15
- package/src/core/evaluator/form-parsers.ts +178 -0
- package/src/core/evaluator/index.ts +7 -9
- package/src/core/evaluator/js-interop.ts +189 -0
- package/src/core/evaluator/quasiquote.ts +14 -8
- package/src/core/evaluator/recur-check.ts +6 -6
- package/src/core/evaluator/special-forms.ts +234 -191
- package/src/core/factories.ts +182 -3
- package/src/core/index.ts +54 -4
- package/src/core/module.ts +136 -0
- package/src/core/ns-forms.ts +107 -0
- package/src/core/printer.ts +371 -11
- package/src/core/reader.ts +84 -33
- package/src/core/registry.ts +209 -0
- package/src/core/runtime.ts +376 -0
- package/src/core/session.ts +253 -487
- package/src/core/stdlib/arithmetic.ts +528 -194
- package/src/core/stdlib/async-fns.ts +132 -0
- package/src/core/stdlib/atoms.ts +291 -56
- package/src/core/stdlib/errors.ts +54 -50
- package/src/core/stdlib/hof.ts +82 -166
- package/src/core/stdlib/js-namespace.ts +344 -0
- package/src/core/stdlib/lazy.ts +34 -0
- package/src/core/stdlib/maps-sets.ts +322 -0
- package/src/core/stdlib/meta.ts +61 -30
- package/src/core/stdlib/predicates.ts +325 -187
- package/src/core/stdlib/regex.ts +126 -98
- package/src/core/stdlib/seq.ts +564 -0
- package/src/core/stdlib/strings.ts +164 -135
- package/src/core/stdlib/transducers.ts +95 -100
- package/src/core/stdlib/utils.ts +292 -130
- package/src/core/stdlib/vars.ts +27 -27
- package/src/core/stdlib/vectors.ts +122 -0
- package/src/core/tokenizer.ts +2 -2
- package/src/core/transformations.ts +117 -9
- package/src/core/types.ts +98 -2
- package/src/host/node-host-module.ts +74 -0
- package/src/{vite-plugin-clj/nrepl-relay.ts → nrepl/relay.ts} +72 -11
- package/src/vite-plugin-clj/codegen.ts +87 -95
- package/src/vite-plugin-clj/index.ts +178 -23
- package/src/vite-plugin-clj/namespace-utils.ts +39 -0
- package/src/vite-plugin-clj/static-analysis.ts +211 -0
- package/src/clojure/demo.clj +0 -72
- package/src/clojure/demo.clj.d.ts +0 -0
- package/src/core/core-env.ts +0 -61
- package/src/core/stdlib/collections.ts +0 -739
- 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
|
+
}
|
package/src/clojure/demo.clj
DELETED
|
@@ -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
|
package/src/core/core-env.ts
DELETED
|
@@ -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
|
-
}
|