conjure-js 0.0.1

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 (80) hide show
  1. package/conjure +0 -0
  2. package/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  3. package/dist/assets/editor.worker-CdQrwHl8.js +26 -0
  4. package/dist/assets/main-A7ZMId9A.css +1 -0
  5. package/dist/assets/main-CmI-7epE.js +3137 -0
  6. package/dist/index.html +195 -0
  7. package/dist/vite.svg +1 -0
  8. package/package.json +68 -0
  9. package/src/bin/__fixtures__/smoke/app/lib.clj +4 -0
  10. package/src/bin/__fixtures__/smoke/app/main.clj +4 -0
  11. package/src/bin/__fixtures__/smoke/repl-smoke.ts +12 -0
  12. package/src/bin/bencode.ts +205 -0
  13. package/src/bin/cli.ts +250 -0
  14. package/src/bin/nrepl-utils.ts +59 -0
  15. package/src/bin/nrepl.ts +393 -0
  16. package/src/bin/version.ts +4 -0
  17. package/src/clojure/core.clj +620 -0
  18. package/src/clojure/core.clj.d.ts +189 -0
  19. package/src/clojure/demo/math.clj +16 -0
  20. package/src/clojure/demo/math.clj.d.ts +4 -0
  21. package/src/clojure/demo.clj +42 -0
  22. package/src/clojure/demo.clj.d.ts +0 -0
  23. package/src/clojure/generated/builtin-namespace-registry.ts +14 -0
  24. package/src/clojure/generated/clojure-core-source.ts +623 -0
  25. package/src/clojure/generated/clojure-string-source.ts +196 -0
  26. package/src/clojure/string.clj +192 -0
  27. package/src/clojure/string.clj.d.ts +25 -0
  28. package/src/core/assertions.ts +134 -0
  29. package/src/core/conversions.ts +108 -0
  30. package/src/core/core-env.ts +58 -0
  31. package/src/core/env.ts +78 -0
  32. package/src/core/errors.ts +39 -0
  33. package/src/core/evaluator/apply.ts +114 -0
  34. package/src/core/evaluator/arity.ts +174 -0
  35. package/src/core/evaluator/collections.ts +25 -0
  36. package/src/core/evaluator/destructure.ts +247 -0
  37. package/src/core/evaluator/dispatch.ts +73 -0
  38. package/src/core/evaluator/evaluate.ts +100 -0
  39. package/src/core/evaluator/expand.ts +79 -0
  40. package/src/core/evaluator/index.ts +72 -0
  41. package/src/core/evaluator/quasiquote.ts +87 -0
  42. package/src/core/evaluator/recur-check.ts +109 -0
  43. package/src/core/evaluator/special-forms.ts +517 -0
  44. package/src/core/factories.ts +155 -0
  45. package/src/core/gensym.ts +9 -0
  46. package/src/core/index.ts +76 -0
  47. package/src/core/positions.ts +38 -0
  48. package/src/core/printer.ts +86 -0
  49. package/src/core/reader.ts +559 -0
  50. package/src/core/scanners.ts +93 -0
  51. package/src/core/session.ts +610 -0
  52. package/src/core/stdlib/arithmetic.ts +361 -0
  53. package/src/core/stdlib/atoms.ts +88 -0
  54. package/src/core/stdlib/collections.ts +784 -0
  55. package/src/core/stdlib/errors.ts +81 -0
  56. package/src/core/stdlib/hof.ts +307 -0
  57. package/src/core/stdlib/meta.ts +48 -0
  58. package/src/core/stdlib/predicates.ts +240 -0
  59. package/src/core/stdlib/regex.ts +238 -0
  60. package/src/core/stdlib/strings.ts +311 -0
  61. package/src/core/stdlib/transducers.ts +256 -0
  62. package/src/core/stdlib/utils.ts +287 -0
  63. package/src/core/tokenizer.ts +437 -0
  64. package/src/core/transformations.ts +75 -0
  65. package/src/core/types.ts +258 -0
  66. package/src/main.ts +1 -0
  67. package/src/monaco-esm.d.ts +7 -0
  68. package/src/playground/clojure-tokens.ts +67 -0
  69. package/src/playground/editor.worker.ts +5 -0
  70. package/src/playground/find-form.ts +138 -0
  71. package/src/playground/playground.ts +342 -0
  72. package/src/playground/samples/00-welcome.clj +385 -0
  73. package/src/playground/samples/01-collections.clj +191 -0
  74. package/src/playground/samples/02-higher-order-functions.clj +215 -0
  75. package/src/playground/samples/03-destructuring.clj +194 -0
  76. package/src/playground/samples/04-strings-and-regex.clj +202 -0
  77. package/src/playground/samples/05-error-handling.clj +212 -0
  78. package/src/repl/repl.ts +116 -0
  79. package/tsconfig.build.json +10 -0
  80. package/tsconfig.json +31 -0
@@ -0,0 +1,212 @@
1
+ (ns user.errors)
2
+
3
+ ;; Deep Dive: Error Handling
4
+ ;;
5
+ ;; Press ⌘+Enter on any form to evaluate it.
6
+
7
+
8
+ ;; try / catch / finally
9
+
10
+ (comment
11
+ ;; No error — returns the value of the body
12
+ (try
13
+ (+ 1 2)) ;; => 3
14
+
15
+ ;; catch with :default — catches anything
16
+ (try
17
+ (/ 1 0)
18
+ (catch :default e
19
+ (str "Caught: " (ex-message e))))
20
+
21
+ ;; finally — always runs, does NOT change the return value
22
+ (try
23
+ (+ 1 2)
24
+ (finally
25
+ (println "always runs"))) ;; prints, returns 3
26
+
27
+ (try
28
+ (/ 1 0)
29
+ (catch :default e
30
+ (println "handling error")
31
+ :recovered)
32
+ (finally
33
+ (println "cleanup"))) ;; => :recovered
34
+ )
35
+
36
+
37
+ ;; throw
38
+ ;;
39
+ ;; You can throw any value — not just error objects.
40
+
41
+ (comment
42
+ (try
43
+ (throw "something went wrong")
44
+ (catch string? e
45
+ (str "got a string: " e)))
46
+
47
+ (try
48
+ (throw :not-found)
49
+ (catch keyword? e
50
+ (str "got a keyword: " e)))
51
+
52
+ (try
53
+ (throw 42)
54
+ (catch number? e
55
+ (str "got a number: " (+ e 1))))
56
+
57
+ (try
58
+ (throw {:type :validation :field :email :msg "invalid"})
59
+ (catch map? e
60
+ (str "validation error on " (:field e))))
61
+ )
62
+
63
+
64
+ ;; Catch Discriminators
65
+ ;;
66
+ ;; The catch clause tests the thrown value with a discriminator:
67
+ ;;
68
+ ;; :default — catches everything
69
+ ;; :error/runtime — catches evaluator errors (type errors, etc.)
70
+ ;; keyword — checks (= thrown discriminator)
71
+ ;; predicate fn — checks (pred thrown-value)
72
+
73
+ (comment
74
+ (defn find-user [id]
75
+ (if (pos? id)
76
+ {:id id :name "Alice"}
77
+ (throw :user/not-found)))
78
+
79
+ (try
80
+ (find-user -1)
81
+ (catch :user/not-found _
82
+ "User not found — check the id"))
83
+
84
+ ;; Multiple catch clauses — matched in order
85
+ (defn risky [x]
86
+ (cond
87
+ (string? x) (throw :bad-type)
88
+ (neg? x) (throw :negative)
89
+ :else (/ 100 x)))
90
+
91
+ (try
92
+ (risky -5)
93
+ (catch :bad-type _ "wrong type")
94
+ (catch :negative _ "negative number")
95
+ (catch :default e (str "unexpected: " e)))
96
+
97
+ (try (risky "oops") (catch :bad-type _ "wrong type") (catch :negative _ "neg"))
98
+ (try (risky 0) (catch :default e (ex-message e)))
99
+
100
+ ;; :error/runtime — catches interpreter-level errors
101
+ (try
102
+ (+ 1 "not a number")
103
+ (catch :error/runtime e
104
+ (str "type error caught: " (ex-message e))))
105
+ )
106
+
107
+
108
+ ;; ex-info: Structured Errors
109
+ ;;
110
+ ;; `ex-info` creates an error with a message AND a data map.
111
+
112
+ (comment
113
+ (try
114
+ (throw (ex-info "User validation failed"
115
+ {:field :email
116
+ :value "not-an-email"
117
+ :code :invalid-format}))
118
+ (catch :default e
119
+ {:message (ex-message e)
120
+ :data (ex-data e)}))
121
+
122
+ ;; ex-info with a cause (chained errors)
123
+ (try
124
+ (try
125
+ (/ 1 0)
126
+ (catch :default cause
127
+ (throw (ex-info "Database query failed"
128
+ {:query "SELECT *"}
129
+ cause))))
130
+ (catch :default e
131
+ {:message (ex-message e)
132
+ :data (ex-data e)
133
+ :cause (ex-message (ex-cause e))}))
134
+ )
135
+
136
+
137
+ ;; Keyword-typed Errors with ex-info
138
+ ;;
139
+ ;; Attach a :type keyword to the ex-info map, then catch by that keyword.
140
+
141
+ (defn parse-age [x]
142
+ (cond
143
+ (not (number? x))
144
+ (throw (ex-info "Not a number" {:value x :type :error/parse}))
145
+
146
+ (neg? x)
147
+ (throw (ex-info "Age cannot be negative" {:value x :type :error/validation}))
148
+
149
+ :else x))
150
+
151
+ (comment
152
+ (try
153
+ (parse-age "hello")
154
+ (catch :error/parse e
155
+ (str "Parse error: " (ex-message e) " (got: " (:value (ex-data e)) ")"))
156
+ (catch :error/validation e
157
+ (str "Validation error: " (ex-message e))))
158
+
159
+ (try
160
+ (parse-age -5)
161
+ (catch :error/parse e (str "parse: " (ex-message e)))
162
+ (catch :error/validation e (str "validation: " (ex-message e))))
163
+
164
+ (parse-age 30) ;; => 30 (no error)
165
+ )
166
+
167
+
168
+ ;; Practical Patterns
169
+
170
+ (comment
171
+ ;; Result map {ok? result/error}
172
+ (defn safe-divide [a b]
173
+ (try
174
+ {:ok? true :result (/ a b)}
175
+ (catch :default e
176
+ {:ok? false :error (ex-message e)})))
177
+
178
+ (safe-divide 10 2) ;; => {:ok? true :result 5}
179
+ (safe-divide 10 0) ;; => {:ok? false :error "..."}
180
+
181
+ ;; Validate before computing
182
+ (defn sqrt [n]
183
+ (when (neg? n)
184
+ (throw (ex-info "Cannot take sqrt of negative number"
185
+ {:value n :type :error/domain})))
186
+ (loop [x (* 0.5 (+ 1.0 n))]
187
+ (let [next-x (* 0.5 (+ x (/ n x)))
188
+ diff (max (- next-x x) (- x next-x))]
189
+ (if (< diff 1e-9)
190
+ next-x
191
+ (recur next-x)))))
192
+
193
+ (try (sqrt 9) (catch :default e (ex-message e))) ;; => 3.0
194
+ (try (sqrt -1) (catch :error/domain e (ex-message e)))
195
+
196
+ ;; Wrapping external errors with context
197
+ (defn load-user [id]
198
+ (try
199
+ (if (= id 42)
200
+ {:id 42 :name "Alice"}
201
+ (throw (ex-info "User not found" {:id id :type :error/not-found})))
202
+ (catch :error/not-found e
203
+ (throw (ex-info (str "Failed to load profile for id=" id)
204
+ {:id id :type :error/load-failed}
205
+ e)))))
206
+
207
+ (try
208
+ (load-user 99)
209
+ (catch :error/load-failed e
210
+ {:msg (ex-message e)
211
+ :cause (ex-message (ex-cause e))}))
212
+ )
@@ -0,0 +1,116 @@
1
+ import { EvaluationError } from '../core/errors'
2
+ import { printString } from '../core/printer'
3
+ import { createSession } from '../core/session'
4
+ import type { Session } from '../core/session'
5
+
6
+ export type ReplEntrySource = {
7
+ kind: 'source'
8
+ text: string
9
+ }
10
+
11
+ export type ReplEntryResult = {
12
+ kind: 'result'
13
+ output: string
14
+ durationMs: number
15
+ }
16
+
17
+ export type ReplEntryError = {
18
+ kind: 'error'
19
+ source: string
20
+ message: string
21
+ durationMs: number
22
+ }
23
+
24
+ export type ReplEntryOutput = {
25
+ kind: 'output'
26
+ text: string
27
+ }
28
+
29
+ export type ReplEntry =
30
+ | ReplEntrySource
31
+ | ReplEntryResult
32
+ | ReplEntryError
33
+ | ReplEntryOutput
34
+
35
+ export interface ReplState {
36
+ session: Session
37
+ /** Submitted expression history for Up/Down navigation */
38
+ history: string[]
39
+ /** Rendered output entries */
40
+ entries: ReplEntry[]
41
+ /** Output collector for current evaluation */
42
+ outputs: string[]
43
+ }
44
+
45
+ function makeSession(addOutput: (text: string) => void): Session {
46
+ return createSession({ output: addOutput })
47
+ }
48
+
49
+ export function makeRepl(): ReplState {
50
+ const state: ReplState = {
51
+ session: undefined as unknown as Session,
52
+ history: [],
53
+ entries: [],
54
+ outputs: [],
55
+ }
56
+ state.session = makeSession((text) => state.outputs.push(text))
57
+ return state
58
+ }
59
+
60
+ export function evalSource(state: ReplState, source: string): ReplEntry[] {
61
+ const trimmed = source.trim()
62
+ if (!trimmed) return []
63
+
64
+ state.history.push(trimmed)
65
+
66
+ // Clear outputs from previous evaluation
67
+ state.outputs = []
68
+ const start = performance.now()
69
+
70
+ try {
71
+ const result = state.session.evaluate(trimmed)
72
+ const end = performance.now()
73
+
74
+ // Build entries in correct order: source, outputs, result
75
+ const entries: ReplEntry[] = []
76
+
77
+ entries.push({ kind: 'source', text: trimmed })
78
+
79
+ for (const text of state.outputs) {
80
+ entries.push({ kind: 'output', text })
81
+ }
82
+
83
+ entries.push({
84
+ kind: 'result',
85
+ output: printString(result),
86
+ durationMs: end - start,
87
+ })
88
+
89
+ state.entries.push(...entries)
90
+ return entries
91
+ } catch (e) {
92
+ const end = performance.now()
93
+ const entry = makeErrorEntry(trimmed, e, end - start)
94
+ state.entries.push(entry)
95
+ return [entry]
96
+ }
97
+ }
98
+
99
+ function makeErrorEntry(
100
+ source: string,
101
+ e: unknown,
102
+ durationMs: number
103
+ ): ReplEntryError {
104
+ const message =
105
+ e instanceof EvaluationError || e instanceof Error ? e.message : String(e)
106
+ return { kind: 'error', source, message, durationMs }
107
+ }
108
+
109
+ export function resetEnv(state: ReplState): void {
110
+ state.outputs = []
111
+ state.session = makeSession((text) => state.outputs.push(text))
112
+ }
113
+
114
+ export function getAllForms(state: ReplState): string {
115
+ return state.history.join('\n')
116
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "exclude": [
4
+ "src/**/__tests__/**",
5
+ "src/**/*.spec.ts",
6
+ "src/**/*.test.ts",
7
+ "src/demo-entry.ts",
8
+ "src/vite-plugin-clj"
9
+ ]
10
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "types": [
8
+ "vite/client",
9
+ "node",
10
+ "bun"
11
+ ],
12
+ "skipLibCheck": true,
13
+
14
+ /* Bundler mode */
15
+ "moduleResolution": "bundler",
16
+ "allowImportingTsExtensions": true,
17
+ "allowArbitraryExtensions": true,
18
+ "verbatimModuleSyntax": true,
19
+ "moduleDetection": "force",
20
+ "noEmit": true,
21
+
22
+ /* Linting */
23
+ "strict": true,
24
+ "noUnusedLocals": true,
25
+ "noUnusedParameters": true,
26
+ "erasableSyntaxOnly": true,
27
+ "noFallthroughCasesInSwitch": true,
28
+ "noUncheckedSideEffectImports": true
29
+ },
30
+ "include": ["src"]
31
+ }