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
@@ -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 { isRegex } from '../assertions'
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): { pattern: string; flags: 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 (!isRegex(val)) {
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 cljString(match[0])
71
- return cljVector(
72
- match.map((m) => (m == null ? cljNil() : cljString(m)))
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?': withDoc(
82
- cljNativeFunction('regexp?', (x: CljValue) =>
83
- cljBoolean(x !== undefined && isRegex(x))
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': withDoc(
90
- cljNativeFunction('re-pattern', (s: CljValue) => {
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 cljRegex(pattern, flags)
99
- }),
100
- '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+".',
101
- [['s']]
102
- ),
103
-
104
- 're-find': withDoc(
105
- cljNativeFunction('re-find', (reVal: CljValue, sVal: CljValue) => {
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 cljNil()
106
+ if (!match) return v.nil()
111
107
  return matchToClj(match)
112
- }),
113
- '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).',
114
- [['re', 's']]
115
- ),
116
-
117
- 're-matches': withDoc(
118
- cljNativeFunction('re-matches', (reVal: CljValue, sVal: CljValue) => {
119
- const re = assertRegex(reVal, 're-matches')
120
- const s = assertStringArg(sVal, 're-matches')
121
- const jsRe = new RegExp(re.pattern, re.flags)
122
- const match = jsRe.exec(s)
123
- if (!match || match.index !== 0 || match[0].length !== s.length) {
124
- return cljNil()
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
- return matchToClj(match)
127
- }),
128
- '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).',
129
- [['re', 's']]
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': withDoc(
133
- cljNativeFunction('re-seq', (reVal: CljValue, sVal: CljValue) => {
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 cljNil()
149
+ if (results.length === 0) return v.nil()
149
150
  return { kind: 'list' as const, value: results }
150
- }),
151
- '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.',
152
- [['re', 's']]
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*': withDoc(
160
- cljNativeFunction('str-split*', (sVal: CljValue, sepVal: CljValue, limitVal?: CljValue) => {
161
- if (sVal === undefined || sVal.kind !== 'string') {
162
- throw new EvaluationError(
163
- `str-split* expects a string as first argument${sVal !== undefined ? `, got ${printString(sVal)}` : ''}`,
164
- { sVal }
165
- )
166
- }
167
- const s = sVal.value
168
- const hasLimit = limitVal !== undefined && limitVal.kind !== 'nil'
169
- const limit: number | undefined =
170
- hasLimit && limitVal!.kind === 'number' ? limitVal!.value : undefined
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
- let jsPattern: string
173
- let jsFlags: string
180
+ let jsPattern: string
181
+ let jsFlags: string
174
182
 
175
- if (sepVal.kind !== 'regex') {
176
- throw new EvaluationError(
177
- `str-split* expects a regex pattern as second argument, got ${printString(sepVal)}`,
178
- { sepVal }
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
- // Empty pattern (#"") splits into individual characters — matching
183
- // Clojure/Java split("") semantics. Unicode-safe via [...s].
184
- if (sepVal.pattern === '') {
185
- const chars = [...s]
186
- if (limit === undefined || limit >= chars.length) {
187
- return cljVector(chars.map(cljString))
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
- jsPattern = sepVal.pattern
195
- jsFlags = sepVal.flags
209
+ jsPattern = sepVal.pattern
210
+ jsFlags = sepVal.flags
196
211
 
197
- const re = new RegExp(jsPattern, jsFlags + 'g')
198
- const rawParts = splitWithRegex(s, re, limit)
212
+ const re = new RegExp(jsPattern, jsFlags + 'g')
213
+ const rawParts = splitWithRegex(s, re, limit)
199
214
 
200
- return cljVector(rawParts.map((p) => cljString(p)))
201
- }),
202
- 'Internal helper for clojure.string/split. Splits string s by a regex or\n string separator. Optional limit keeps all parts when provided.',
203
- [['s', 'sep'], ['s', 'sep', 'limit']]
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(s: string, re: RegExp, limit: number | undefined): string[] {
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