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
package/src/core/stdlib/regex.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
// Regex stdlib: regexp?, re-pattern, re-find, re-matches, re-seq
|
|
2
2
|
// Also exports str-split* used internally by clojure.string/split.
|
|
3
|
-
import {
|
|
3
|
+
import { is } from '../assertions'
|
|
4
4
|
import { EvaluationError } from '../errors'
|
|
5
|
-
import {
|
|
6
|
-
cljBoolean,
|
|
7
|
-
cljNativeFunction,
|
|
8
|
-
cljNil,
|
|
9
|
-
cljRegex,
|
|
10
|
-
cljString,
|
|
11
|
-
cljVector,
|
|
12
|
-
withDoc,
|
|
13
|
-
} from '../factories'
|
|
5
|
+
import { v } from '../factories'
|
|
14
6
|
import { printString } from '../printer'
|
|
15
7
|
import type { CljRegex, CljValue } from '../types'
|
|
16
8
|
|
|
@@ -19,7 +11,10 @@ import type { CljRegex, CljValue } from '../types'
|
|
|
19
11
|
// Mirrors the logic in reader.ts so that re-pattern can also process flags.
|
|
20
12
|
// Only leading standalone (?flags) groups are stripped. (?:...) is untouched.
|
|
21
13
|
// ---------------------------------------------------------------------------
|
|
22
|
-
export function extractInlineFlags(raw: string): {
|
|
14
|
+
export function extractInlineFlags(raw: string): {
|
|
15
|
+
pattern: string
|
|
16
|
+
flags: string
|
|
17
|
+
} {
|
|
23
18
|
let remaining = raw
|
|
24
19
|
let flags = ''
|
|
25
20
|
const flagGroupRe = /^\(\?([imsx]+)\)/
|
|
@@ -44,7 +39,7 @@ export function extractInlineFlags(raw: string): { pattern: string; flags: strin
|
|
|
44
39
|
// ---------------------------------------------------------------------------
|
|
45
40
|
|
|
46
41
|
function assertRegex(val: CljValue, fnName: string): CljRegex {
|
|
47
|
-
if (!
|
|
42
|
+
if (!is.regex(val)) {
|
|
48
43
|
throw new EvaluationError(
|
|
49
44
|
`${fnName} expects a regex as first argument, got ${printString(val)}`,
|
|
50
45
|
{ val }
|
|
@@ -67,9 +62,11 @@ function assertStringArg(val: CljValue, fnName: string): string {
|
|
|
67
62
|
// - no capturing groups → CljString
|
|
68
63
|
// - with capturing groups → CljVector of [whole, g1, g2, ...] with nil for unmatched groups
|
|
69
64
|
function matchToClj(match: RegExpExecArray): CljValue {
|
|
70
|
-
if (match.length === 1) return
|
|
71
|
-
return
|
|
72
|
-
match.map(
|
|
65
|
+
if (match.length === 1) return v.string(match[0])
|
|
66
|
+
return v.vector(
|
|
67
|
+
match.map(function mapMatchToClj(m) {
|
|
68
|
+
return m == null ? v.nil() : v.string(m)
|
|
69
|
+
})
|
|
73
70
|
)
|
|
74
71
|
}
|
|
75
72
|
|
|
@@ -78,16 +75,14 @@ function matchToClj(match: RegExpExecArray): CljValue {
|
|
|
78
75
|
// ---------------------------------------------------------------------------
|
|
79
76
|
|
|
80
77
|
export const regexFunctions: Record<string, CljValue> = {
|
|
81
|
-
'regexp?':
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
'Returns true if x is a regular expression pattern.',
|
|
86
|
-
[['x']]
|
|
87
|
-
),
|
|
78
|
+
'regexp?': v
|
|
79
|
+
.nativeFn('regexp?', function regexpPredImpl(x: CljValue) {
|
|
80
|
+
return v.boolean(x !== undefined && is.regex(x))
|
|
81
|
+
})
|
|
82
|
+
.doc('Returns true if x is a regular expression pattern.', [['x']]),
|
|
88
83
|
|
|
89
|
-
're-pattern':
|
|
90
|
-
|
|
84
|
+
're-pattern': v
|
|
85
|
+
.nativeFn('re-pattern', function rePatternImpl(s: CljValue) {
|
|
91
86
|
if (s === undefined || s.kind !== 'string') {
|
|
92
87
|
throw new EvaluationError(
|
|
93
88
|
`re-pattern expects a string argument${s !== undefined ? `, got ${printString(s)}` : ''}`,
|
|
@@ -95,42 +90,48 @@ export const regexFunctions: Record<string, CljValue> = {
|
|
|
95
90
|
)
|
|
96
91
|
}
|
|
97
92
|
const { pattern, flags } = extractInlineFlags(s.value)
|
|
98
|
-
return
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
93
|
+
return v.regex(pattern, flags)
|
|
94
|
+
})
|
|
95
|
+
.doc(
|
|
96
|
+
'Returns an instance of java.util.regex.Pattern, for use, e.g. in re-matcher.\n (re-pattern "\\\\d+") produces the same pattern as #"\\d+".',
|
|
97
|
+
[['s']]
|
|
98
|
+
),
|
|
99
|
+
|
|
100
|
+
're-find': v
|
|
101
|
+
.nativeFn('re-find', function reFindImpl(reVal: CljValue, sVal: CljValue) {
|
|
106
102
|
const re = assertRegex(reVal, 're-find')
|
|
107
103
|
const s = assertStringArg(sVal, 're-find')
|
|
108
104
|
const jsRe = new RegExp(re.pattern, re.flags)
|
|
109
105
|
const match = jsRe.exec(s)
|
|
110
|
-
if (!match) return
|
|
106
|
+
if (!match) return v.nil()
|
|
111
107
|
return matchToClj(match)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
108
|
+
})
|
|
109
|
+
.doc(
|
|
110
|
+
'Returns the next regex match, if any, of string to pattern, using\n java.util.regex.Matcher.find(). Returns the match or nil. When there\n are groups, returns a vector of the whole match and groups (nil for\n unmatched optional groups).',
|
|
111
|
+
[['re', 's']]
|
|
112
|
+
),
|
|
113
|
+
|
|
114
|
+
're-matches': v
|
|
115
|
+
.nativeFn(
|
|
116
|
+
're-matches',
|
|
117
|
+
function reMatchesImpl(reVal: CljValue, sVal: CljValue) {
|
|
118
|
+
const re = assertRegex(reVal, 're-matches')
|
|
119
|
+
const s = assertStringArg(sVal, 're-matches')
|
|
120
|
+
const jsRe = new RegExp(re.pattern, re.flags)
|
|
121
|
+
const match = jsRe.exec(s)
|
|
122
|
+
if (!match || match.index !== 0 || match[0].length !== s.length) {
|
|
123
|
+
return v.nil()
|
|
124
|
+
}
|
|
125
|
+
return matchToClj(match)
|
|
125
126
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
)
|
|
128
|
+
.doc(
|
|
129
|
+
'Returns the match, if any, of string to pattern, using\n java.util.regex.Matcher.matches(). The entire string must match.\n Returns the match or nil. When there are groups, returns a vector\n of the whole match and groups (nil for unmatched optional groups).',
|
|
130
|
+
[['re', 's']]
|
|
131
|
+
),
|
|
131
132
|
|
|
132
|
-
're-seq':
|
|
133
|
-
|
|
133
|
+
're-seq': v
|
|
134
|
+
.nativeFn('re-seq', function reSeqImpl(reVal: CljValue, sVal: CljValue) {
|
|
134
135
|
const re = assertRegex(reVal, 're-seq')
|
|
135
136
|
const s = assertStringArg(sVal, 're-seq')
|
|
136
137
|
// Always create a fresh regex with the g flag for exec looping
|
|
@@ -145,67 +146,94 @@ export const regexFunctions: Record<string, CljValue> = {
|
|
|
145
146
|
}
|
|
146
147
|
results.push(matchToClj(match))
|
|
147
148
|
}
|
|
148
|
-
if (results.length === 0) return
|
|
149
|
+
if (results.length === 0) return v.nil()
|
|
149
150
|
return { kind: 'list' as const, value: results }
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
})
|
|
152
|
+
.doc(
|
|
153
|
+
'Returns a lazy sequence of successive matches of pattern in string,\n using java.util.regex.Matcher.find(), each such match processed with\n re-groups.',
|
|
154
|
+
[['re', 's']]
|
|
155
|
+
),
|
|
154
156
|
|
|
155
157
|
// Internal helper used by clojure.string/split.
|
|
156
158
|
// Accepts a CljRegex or CljString as separator.
|
|
157
159
|
// When no limit is given, trailing empty strings are dropped (Clojure default).
|
|
158
160
|
// When a limit is given, all parts including trailing empties are kept.
|
|
159
|
-
'str-split*':
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
161
|
+
'str-split*': v
|
|
162
|
+
.nativeFn(
|
|
163
|
+
'str-split*',
|
|
164
|
+
function strSplitImpl(
|
|
165
|
+
sVal: CljValue,
|
|
166
|
+
sepVal: CljValue,
|
|
167
|
+
limitVal?: CljValue
|
|
168
|
+
) {
|
|
169
|
+
if (sVal === undefined || sVal.kind !== 'string') {
|
|
170
|
+
throw new EvaluationError(
|
|
171
|
+
`str-split* expects a string as first argument${sVal !== undefined ? `, got ${printString(sVal)}` : ''}`,
|
|
172
|
+
{ sVal }
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
const s = sVal.value
|
|
176
|
+
const hasLimit = limitVal !== undefined && limitVal.kind !== 'nil'
|
|
177
|
+
const limit: number | undefined =
|
|
178
|
+
hasLimit && limitVal!.kind === 'number' ? limitVal!.value : undefined
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
|
|
180
|
+
let jsPattern: string
|
|
181
|
+
let jsFlags: string
|
|
174
182
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
183
|
+
if (sepVal.kind !== 'regex') {
|
|
184
|
+
throw new EvaluationError(
|
|
185
|
+
`str-split* expects a regex pattern as second argument, got ${printString(sepVal)}`,
|
|
186
|
+
{ sepVal }
|
|
187
|
+
)
|
|
188
|
+
}
|
|
181
189
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
190
|
+
// Empty pattern (#"") splits into individual characters — matching
|
|
191
|
+
// Clojure/Java split("") semantics. Unicode-safe via [...s].
|
|
192
|
+
if (sepVal.pattern === '') {
|
|
193
|
+
const chars = [...s]
|
|
194
|
+
if (limit === undefined || limit >= chars.length) {
|
|
195
|
+
return v.vector(chars.map(v.string))
|
|
196
|
+
}
|
|
197
|
+
// limit < chars.length: first (limit-1) chars + rest of string as final part
|
|
198
|
+
const parts = [
|
|
199
|
+
...chars.slice(0, limit - 1),
|
|
200
|
+
chars.slice(limit - 1).join(''),
|
|
201
|
+
]
|
|
202
|
+
return v.vector(
|
|
203
|
+
parts.map(function mapPartToString(p) {
|
|
204
|
+
return v.string(p)
|
|
205
|
+
})
|
|
206
|
+
)
|
|
188
207
|
}
|
|
189
|
-
// limit < chars.length: first (limit-1) chars + rest of string as final part
|
|
190
|
-
const parts = [...chars.slice(0, limit - 1), chars.slice(limit - 1).join('')]
|
|
191
|
-
return cljVector(parts.map(cljString))
|
|
192
|
-
}
|
|
193
208
|
|
|
194
|
-
|
|
195
|
-
|
|
209
|
+
jsPattern = sepVal.pattern
|
|
210
|
+
jsFlags = sepVal.flags
|
|
196
211
|
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
const re = new RegExp(jsPattern, jsFlags + 'g')
|
|
213
|
+
const rawParts = splitWithRegex(s, re, limit)
|
|
199
214
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
215
|
+
return v.vector(
|
|
216
|
+
rawParts.map(function mapRawPartToString(p) {
|
|
217
|
+
return v.string(p)
|
|
218
|
+
})
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
.doc(
|
|
223
|
+
'Internal helper for clojure.string/split. Splits string s by a regex or\n string separator. Optional limit keeps all parts when provided.',
|
|
224
|
+
[
|
|
225
|
+
['s', 'sep'],
|
|
226
|
+
['s', 'sep', 'limit'],
|
|
227
|
+
]
|
|
228
|
+
),
|
|
205
229
|
}
|
|
206
230
|
|
|
207
231
|
// Performs the actual split, applying limit and trailing-empty-drop semantics.
|
|
208
|
-
function splitWithRegex(
|
|
232
|
+
function splitWithRegex(
|
|
233
|
+
s: string,
|
|
234
|
+
re: RegExp,
|
|
235
|
+
limit: number | undefined
|
|
236
|
+
): string[] {
|
|
209
237
|
const parts: string[] = []
|
|
210
238
|
let lastIndex = 0
|
|
211
239
|
let match: RegExpExecArray | null
|