kimchilang 1.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 (90) hide show
  1. package/.github/workflows/ci.yml +66 -0
  2. package/README.md +1547 -0
  3. package/create-kimchi-app/README.md +44 -0
  4. package/create-kimchi-app/index.js +214 -0
  5. package/create-kimchi-app/package.json +22 -0
  6. package/editors/README.md +121 -0
  7. package/editors/sublime/KimchiLang.sublime-syntax +138 -0
  8. package/editors/vscode/README.md +90 -0
  9. package/editors/vscode/kimchilang-1.1.0.vsix +0 -0
  10. package/editors/vscode/language-configuration.json +37 -0
  11. package/editors/vscode/package.json +55 -0
  12. package/editors/vscode/src/extension.js +354 -0
  13. package/editors/vscode/syntaxes/kimchi.tmLanguage.json +215 -0
  14. package/examples/api/client.km +36 -0
  15. package/examples/async_pipe.km +58 -0
  16. package/examples/basic.kimchi +109 -0
  17. package/examples/cli_framework/README.md +92 -0
  18. package/examples/cli_framework/calculator.km +61 -0
  19. package/examples/cli_framework/deploy.km +126 -0
  20. package/examples/cli_framework/greeter.km +26 -0
  21. package/examples/config.static +27 -0
  22. package/examples/config.static.js +10 -0
  23. package/examples/env_test.km +37 -0
  24. package/examples/fibonacci.kimchi +17 -0
  25. package/examples/greeter.km +15 -0
  26. package/examples/hello.js +1 -0
  27. package/examples/hello.kimchi +3 -0
  28. package/examples/js_interop.km +42 -0
  29. package/examples/logger_example.km +34 -0
  30. package/examples/memo_fibonacci.km +17 -0
  31. package/examples/myapp/lib/http.js +14 -0
  32. package/examples/myapp/lib/http.km +16 -0
  33. package/examples/myapp/main.km +16 -0
  34. package/examples/myapp/main_with_mock.km +42 -0
  35. package/examples/myapp/services/api.js +18 -0
  36. package/examples/myapp/services/api.km +18 -0
  37. package/examples/new_features.kimchi +52 -0
  38. package/examples/project_example.static +20 -0
  39. package/examples/readme_examples.km +240 -0
  40. package/examples/reduce_pattern_match.km +85 -0
  41. package/examples/regex_match.km +46 -0
  42. package/examples/sample.js +45 -0
  43. package/examples/sample.km +39 -0
  44. package/examples/secrets.static +35 -0
  45. package/examples/secrets.static.js +30 -0
  46. package/examples/shell-example.mjs +144 -0
  47. package/examples/shell_example.km +19 -0
  48. package/examples/stdlib_test.km +22 -0
  49. package/examples/test_example.km +69 -0
  50. package/examples/testing/README.md +88 -0
  51. package/examples/testing/http_client.km +18 -0
  52. package/examples/testing/math.km +48 -0
  53. package/examples/testing/math.test.km +93 -0
  54. package/examples/testing/user_service.km +29 -0
  55. package/examples/testing/user_service.test.km +72 -0
  56. package/examples/use-config.mjs +141 -0
  57. package/examples/use_config.km +13 -0
  58. package/install.sh +59 -0
  59. package/package.json +29 -0
  60. package/pantry/acorn/index.km +1 -0
  61. package/pantry/is_number/index.km +1 -0
  62. package/pantry/is_odd/index.km +2 -0
  63. package/project.static +6 -0
  64. package/src/cli.js +1245 -0
  65. package/src/generator.js +1241 -0
  66. package/src/index.js +141 -0
  67. package/src/js2km.js +568 -0
  68. package/src/lexer.js +822 -0
  69. package/src/linter.js +810 -0
  70. package/src/package-manager.js +307 -0
  71. package/src/parser.js +1876 -0
  72. package/src/static-parser.js +500 -0
  73. package/src/typechecker.js +950 -0
  74. package/stdlib/array.km +0 -0
  75. package/stdlib/bitwise.km +38 -0
  76. package/stdlib/console.km +49 -0
  77. package/stdlib/date.km +97 -0
  78. package/stdlib/function.km +44 -0
  79. package/stdlib/http.km +197 -0
  80. package/stdlib/http.md +333 -0
  81. package/stdlib/index.km +26 -0
  82. package/stdlib/json.km +17 -0
  83. package/stdlib/logger.js +114 -0
  84. package/stdlib/logger.km +104 -0
  85. package/stdlib/math.km +120 -0
  86. package/stdlib/object.km +41 -0
  87. package/stdlib/promise.km +33 -0
  88. package/stdlib/string.km +93 -0
  89. package/stdlib/testing.md +265 -0
  90. package/test/test.js +599 -0
package/README.md ADDED
@@ -0,0 +1,1547 @@
1
+ # KimchiLang 🌶️
2
+
3
+ *Some will think it stinks, others will love it—no matter what it's spicy and good for you!*
4
+
5
+ A modern, expressive programming language that transpiles to JavaScript.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Features](#features)
10
+ - [Installation](#installation)
11
+ - [Quick Start](#quick-start)
12
+ - [Language Guide](#language-guide)
13
+ - [Scope and Design Philosophy](#scope-and-design-philosophy)
14
+ - [Variables](#variables)
15
+ - [Type Inference](#type-inference)
16
+ - [Module Visibility (expose)](#module-visibility-expose)
17
+ - [Secrets](#secrets)
18
+ - [Functions](#functions)
19
+ - [Enums](#enums)
20
+ - [Anonymous Functions (Arrow Functions)](#anonymous-functions-arrow-functions)
21
+ - [Control Flow](#control-flow)
22
+ - [Flow Operator](#flow-operator)
23
+ - [Pattern Matching](#pattern-matching)
24
+ - [Arrays & Objects](#arrays--objects)
25
+ - [Safe Member Access](#safe-member-access)
26
+ - [String Interpolation](#string-interpolation)
27
+ - [Pipe Operator](#pipe-operator)
28
+ - [Memoized Functions](#memoized-functions)
29
+ - [Error Handling](#error-handling)
30
+ - [JavaScript Interop](#javascript-interop)
31
+ - [Shell Interop](#shell-interop)
32
+ - [Static Files](#static-files)
33
+ - [Dependency Injection System](#dependency-injection-system)
34
+ - [Module Arguments](#module-arguments)
35
+ - [CLI Commands](#cli-commands)
36
+ - [Module Execution](#module-execution)
37
+ - [Basic Commands](#basic-commands)
38
+ - [Reverse Transpiler](#reverse-transpiler-javascript-to-kimchilang)
39
+ - [NPM Integration](#npm-integration)
40
+ - [Editor Extensions](#editor-extensions)
41
+ - [Windsurf](#windsurf)
42
+ - [VS Code](#vs-code)
43
+ - [Other Editors](#other-editors)
44
+ - [Standard Library](#standard-library)
45
+ - [Logger](#logger)
46
+ - [Bitwise](#bitwise)
47
+ - [Package Management](#package-management)
48
+ - [Testing](#testing)
49
+ - [Test Syntax](#test-syntax)
50
+ - [Matchers](#matchers)
51
+ - [Testing with Mocks](#testing-with-mocks)
52
+ - [Running Tests](#running-tests)
53
+ - [File Extensions](#file-extensions)
54
+ - [How It Works](#how-it-works)
55
+ - [Examples](#examples)
56
+ - [License](#license)
57
+
58
+ ## Features
59
+
60
+ - **Clean Syntax** - Python-inspired readability with JavaScript power
61
+ - **Modern Operators** - Pipe operator (`~>`), flow operator (`>>`), range expressions (`0..10`), spread operator
62
+ - **String Interpolation** - Easy string formatting with `"Hello ${name}!"`
63
+ - **Purely Functional** - No classes, no `this`, no global scope
64
+ - **Deeply Immutable** - All values are immutable with compile-time checking
65
+ - **Pattern Matching** - `match`/`when` expressions for elegant control flow
66
+ - **Arrow Functions** - Concise lambda syntax
67
+ - **Print Statement** - Built-in `print` for quick debugging
68
+ - **Strict Equality** - `==` compiles to `===` for safer comparisons
69
+ - **Safe Member Access** - All property access is null-safe by default
70
+ - **Memoization** - Built-in `memo` keyword for memoized functions
71
+ - **Type Inference** - Compile-time type checking without annotations
72
+ - **JavaScript Interop** - Embed raw JavaScript with `js { }` blocks
73
+
74
+ ## Installation
75
+
76
+ ```bash
77
+ # Clone the repository
78
+ git clone https://github.com/danajanezic/kimchilang.git
79
+ cd kimchilang
80
+
81
+ # Run the installer (installs dependencies and links the 'kimchi' command)
82
+ ./install.sh
83
+ ```
84
+
85
+ After installation, the `kimchi` command is available globally:
86
+
87
+ ```bash
88
+ kimchi run examples/hello.kimchi
89
+ kimchi compile app.kimchi
90
+ kimchi convert input.js
91
+ kimchi help
92
+ ```
93
+
94
+ **Manual installation** (if you prefer not to use the installer):
95
+
96
+ ```bash
97
+ npm install
98
+ npm link
99
+ ```
100
+
101
+ ## Quick Start
102
+
103
+ ### Create a New Project
104
+
105
+ ```bash
106
+ npx create-kimchi-app my-app
107
+ cd my-app
108
+ kimchi src.main
109
+ ```
110
+
111
+ This creates a new project with:
112
+ - `src/main.km` - Main entry point
113
+ - `lib/utils.km` - Example utility module
114
+ - `tests/utils.test.km` - Example tests
115
+ - `project.static` - Project configuration
116
+
117
+ ### Or Create a Single File
118
+
119
+ Create a file called `hello.kimchi`:
120
+
121
+ ```kimchi
122
+ print "Hello, KimchiLang!"
123
+
124
+ fn greet(name) {
125
+ return "Welcome, " + name + "!"
126
+ }
127
+
128
+ print greet("Developer")
129
+ ```
130
+
131
+ Run it:
132
+
133
+ ```bash
134
+ kimchi run hello.kimchi
135
+ ```
136
+
137
+ ## Language Guide
138
+
139
+ ### Scope and Design Philosophy
140
+
141
+ KimchiLang is a **purely functional language** with these core principles:
142
+
143
+ - **No global scope** - Everything is always local
144
+ - **No `this` keyword** - No object-oriented programming
145
+ - **No classes** - Use functions and modules for code organization
146
+ - **All values are immutable** - Enforced at compile-time
147
+
148
+ ### Variables
149
+
150
+ KimchiLang uses `dec` for all variable declarations. All variables are **deeply immutable** - both the variable and any nested properties cannot be reassigned.
151
+
152
+ ```kimchi
153
+ dec name = "Alice"
154
+ dec PI = 3.14159
155
+ dec config = {
156
+ api: {
157
+ url: "https://api.example.com",
158
+ timeout: 5000
159
+ }
160
+ }
161
+ ```
162
+
163
+ **Destructuring:**
164
+
165
+ ```kimchi
166
+ // Object destructuring
167
+ dec person = { name: "Alice", age: 30, city: "NYC" }
168
+ dec { name, age } = person
169
+
170
+ // With renaming
171
+ dec { name: userName, city: userCity } = person
172
+
173
+ // Array destructuring
174
+ dec numbers = [1, 2, 3, 4, 5]
175
+ dec [first, second, third] = numbers
176
+
177
+ // Skip elements with holes
178
+ dec [a, , c] = numbers // a=1, c=3
179
+ ```
180
+
181
+ **Compile-time immutability checking:**
182
+
183
+ ```kimchi
184
+ dec obj = { foo: { bar: "baz" } }
185
+
186
+ obj = {} // Compile error: Cannot reassign 'obj'
187
+ obj.foo = {} // Compile error: Cannot reassign 'obj.foo'
188
+ obj.foo.bar = "new" // Compile error: Cannot reassign 'obj.foo.bar'
189
+ ```
190
+
191
+ At runtime, `dec` values are wrapped with `Object.freeze` recursively for additional protection.
192
+
193
+ ### Type Inference
194
+
195
+ KimchiLang performs compile-time type checking without requiring type annotations. Types are inferred from values and usage:
196
+
197
+ ```kimchi
198
+ dec person = { name: "Alice", age: 30 }
199
+ print person.email // Compile error: Property 'email' does not exist on type { name: string, age: number }
200
+
201
+ dec x = 42
202
+ x() // Compile error: Type 'number' is not callable
203
+
204
+ enum Color { Red, Green, Blue }
205
+ print Color.Yellow // Compile error: Property 'Yellow' does not exist on enum 'Color'
206
+ ```
207
+
208
+ The type checker catches:
209
+ - **Property access on non-existent properties** for known object shapes
210
+ - **Calling non-functions** (e.g., calling a number or string)
211
+ - **Invalid enum member access**
212
+ - **Destructuring non-existent properties**
213
+ - **Type mismatches in dependency injection** (when overriding module deps)
214
+
215
+ ### Module Visibility (expose)
216
+
217
+ By default, all declarations are **private**. Use the `expose` keyword to make them available to other modules:
218
+
219
+ ```kimchi
220
+ // Private - only accessible within this module
221
+ dec internalConfig = { secret: "hidden" }
222
+ fn helperFn() { return "internal" }
223
+
224
+ // Public - accessible by modules that depend on this one
225
+ expose dec API_VERSION = "1.0"
226
+ expose fn greet(name) { return "Hello, " + name }
227
+ ```
228
+
229
+ Attempting to access an unexposed member from a dependency will result in a compile-time error.
230
+
231
+ ### Secrets
232
+
233
+ KimchiLang provides built-in protection for sensitive values like API keys, tokens, and passwords using the `secret` modifier.
234
+
235
+ **Declaring secrets:**
236
+
237
+ ```kimchi
238
+ // Secret variables
239
+ secret dec apiKey = "sk-1234567890"
240
+ secret dec dbPassword = "super-secret"
241
+
242
+ // Secret environment variables
243
+ secret env DATABASE_URL
244
+
245
+ // Secret module arguments
246
+ secret arg authToken
247
+ secret !arg apiKey // Required secret argument
248
+ ```
249
+
250
+ **How secrets are protected:**
251
+
252
+ 1. **Masked in output** - When converted to a string (e.g., in error messages or logs), secrets display as `********` instead of their actual value:
253
+
254
+ ```kimchi
255
+ secret dec apiKey = "sk-1234567890"
256
+ print "Key: ${apiKey}" // Output: "Key: ********"
257
+ ```
258
+
259
+ 2. **Compile-time protection in JS interop** - Secrets cannot be passed to `console.log` or other console methods inside `js { }` blocks:
260
+
261
+ ```kimchi
262
+ secret dec apiKey = "sk-1234567890"
263
+
264
+ // This will FAIL at compile time:
265
+ js(apiKey) {
266
+ console.log(apiKey); // Error: Cannot pass secret 'apiKey' to console.log
267
+ }
268
+
269
+ // This is allowed (using secret for its intended purpose):
270
+ js(apiKey) {
271
+ return fetch(url, { headers: { Authorization: apiKey } });
272
+ }
273
+ ```
274
+
275
+ The compiler checks for `console.log`, `console.error`, `console.warn`, `console.info`, `console.debug`, and `console.trace`.
276
+
277
+ 3. **Value access** - To get the actual value of a secret (e.g., for API calls), use the `.value` property:
278
+
279
+ ```kimchi
280
+ secret dec apiKey = "sk-1234567890"
281
+
282
+ // In JS interop, the value is accessible normally
283
+ dec response = js(apiKey) {
284
+ return fetch("https://api.example.com", {
285
+ headers: { "Authorization": "Bearer " + apiKey }
286
+ });
287
+ }
288
+ ```
289
+
290
+ **Best practices:**
291
+
292
+ - Use `secret` for all sensitive values (API keys, passwords, tokens)
293
+ - Use `secret env` for environment variables containing credentials
294
+ - Use `secret arg` for sensitive module arguments
295
+ - Never log secrets - the compiler will catch attempts in JS blocks
296
+ - The `_Secret` wrapper ensures secrets don't accidentally appear in stack traces or error messages
297
+
298
+ ### Functions
299
+
300
+ ```kimchi
301
+ expose fn add(a, b) {
302
+ return a + b
303
+ }
304
+
305
+ // Async functions
306
+ async fn fetchData(url) {
307
+ dec response = await fetch(url)
308
+ dec data = await response.json()
309
+ return data
310
+ }
311
+
312
+ // Async memoized functions
313
+ async memo cachedFetch(url) {
314
+ dec response = await fetch(url)
315
+ return await response.json()
316
+ }
317
+
318
+ // Default parameters
319
+ fn greet(name = "World") {
320
+ return "Hello, " + name
321
+ }
322
+
323
+ greet() // "Hello, World"
324
+ greet("Alice") // "Hello, Alice"
325
+
326
+ // Rest parameters
327
+ fn sum(...nums) {
328
+ return nums.reduce((acc, n) => acc + n, 0)
329
+ }
330
+
331
+ sum(1, 2, 3, 4, 5) // 15
332
+
333
+ // Combined
334
+ fn log(prefix, separator = ": ", ...messages) {
335
+ return prefix + separator + messages.join(", ")
336
+ }
337
+ ```
338
+
339
+ ### Enums
340
+
341
+ Enums define a set of named constants with auto-incrementing numeric values:
342
+
343
+ ```kimchi
344
+ enum Color {
345
+ Red, // 0
346
+ Green, // 1
347
+ Blue // 2
348
+ }
349
+
350
+ print Color.Red // 0
351
+ print Color.Green // 1
352
+
353
+ // Explicit values
354
+ enum HttpStatus {
355
+ OK = 200,
356
+ NotFound = 404,
357
+ ServerError = 500
358
+ }
359
+
360
+ // Mixed (auto-increment continues from last explicit value)
361
+ enum Priority {
362
+ Low, // 0
363
+ Medium, // 1
364
+ High = 10, // 10
365
+ Critical // 11
366
+ }
367
+ ```
368
+
369
+ Enums are frozen objects and can be used with pattern matching:
370
+
371
+ ```kimchi
372
+ fn getStatusMessage(status) {
373
+ |status == HttpStatus.OK| => { return "Success" }
374
+ |status == HttpStatus.NotFound| => { return "Not Found" }
375
+ |true| => { return "Unknown" }
376
+ }
377
+ ```
378
+
379
+ ### Anonymous Functions (Arrow Functions)
380
+
381
+ KimchiLang supports arrow functions for concise anonymous function expressions:
382
+
383
+ ```kimchi
384
+ // Single parameter (no parentheses needed)
385
+ dec double = x => x * 2
386
+
387
+ // Multiple parameters
388
+ dec add = (a, b) => a + b
389
+
390
+ // Block body for multiple statements
391
+ dec process = (x) => {
392
+ dec result = x * 2
393
+ return result + 1
394
+ }
395
+
396
+ // As callbacks
397
+ dec numbers = [1, 2, 3, 4, 5]
398
+ dec doubled = numbers.map(x => x * 2)
399
+ dec sum = numbers.reduce((acc, n) => acc + n, 0)
400
+ ```
401
+
402
+ **Pattern matching in arrow functions:**
403
+
404
+ Arrow functions with block bodies support pattern matching:
405
+
406
+ ```kimchi
407
+ dec categorize = (item) => {
408
+ |item.type == "fruit"| => { return "produce" }
409
+ |item.type == "meat"| => { return "protein" }
410
+ |true| => { return "other" }
411
+ }
412
+
413
+ // Inline with reduce
414
+ dec balance = transactions.reduce((acc, tx) => {
415
+ |tx.type == "credit"| => { return acc + tx.amount }
416
+ |tx.type == "debit"| => { return acc - tx.amount }
417
+ |true| => { return acc }
418
+ }, 0)
419
+ ```
420
+
421
+ ### Control Flow
422
+
423
+ ```kimchi
424
+ // If/Elif/Else
425
+ if score >= 90 {
426
+ print "A"
427
+ } elif score >= 80 {
428
+ print "B"
429
+ } else {
430
+ print "C"
431
+ }
432
+
433
+ // While loop (use with JS interop for mutable state)
434
+ js {
435
+ let count = 0;
436
+ while (count < 3) {
437
+ console.log("Count: " + count);
438
+ count++;
439
+ }
440
+ }
441
+
442
+ // For loop (for-in)
443
+ for item in items {
444
+ print item
445
+ }
446
+
447
+ // Range expressions
448
+ for i in 0..5 {
449
+ print i // 0, 1, 2, 3, 4
450
+ }
451
+ ```
452
+
453
+ ### Flow Operator
454
+
455
+ Create composed functions with the `>>` flow operator:
456
+
457
+ ```kimchi
458
+ fn addOne(x) { return x + 1 }
459
+ fn double(x) { return x * 2 }
460
+ fn square(x) { return x * x }
461
+
462
+ // Create a composed function
463
+ transform >> addOne double square
464
+
465
+ // Call it later
466
+ dec result = await transform(5) // square(double(addOne(5))) = 144
467
+ ```
468
+
469
+ The flow syntax `name >> fn1 fn2 fn3` creates a new function `name` that composes `fn1`, `fn2`, and `fn3`. When called, arguments are passed to `fn1`, then the result flows through `fn2`, then `fn3`.
470
+
471
+ **Async Support:**
472
+
473
+ Flow-composed functions are async and handle both sync and async functions:
474
+
475
+ ```kimchi
476
+ async fn fetchUser(id) { return { id: id, name: "User" + id } }
477
+ async fn enrichUser(user) { return { ...user, role: "admin" } }
478
+ fn formatUser(user) { return "${user.name} (${user.role})" }
479
+
480
+ // Create an async pipeline
481
+ processUser >> fetchUser enrichUser formatUser
482
+
483
+ async fn main() {
484
+ dec result = await processUser(1) // "User1 (admin)"
485
+ print result
486
+ }
487
+ ```
488
+
489
+ **Difference from pipe operator:**
490
+ - `~>` (pipe): Immediately executes — `5 ~> double ~> addOne` returns a Promise
491
+ - `>>` (flow): Creates a reusable async function — `transform >> double addOne` creates a function you call later
492
+
493
+ ### Pattern Matching
494
+
495
+ Standalone conditional pattern matching that returns from the enclosing function:
496
+
497
+ ```kimchi
498
+ fn handleStatus(status) {
499
+ |status == 200| => print "OK"
500
+ |status == 404| => print "Not Found"
501
+ |status == 500| => print "Server Error"
502
+ }
503
+ ```
504
+
505
+ Each case uses `|condition|` delimiters followed by `=>` and the code to execute. When a condition matches, the code runs and the function returns.
506
+
507
+ ### Arrays & Objects
508
+
509
+ ```kimchi
510
+ dec numbers = [1, 2, 3, 4, 5]
511
+ dec person = {
512
+ name: "Bob",
513
+ age: 30
514
+ }
515
+
516
+ // Spread operator
517
+ dec more = [...numbers, 6, 7, 8]
518
+
519
+ // Object spread
520
+ dec updated = { ...person, age: 31 }
521
+ ```
522
+
523
+ ### Safe Member Access
524
+
525
+ All property access in KimchiLang is **null-safe by default**. The dot operator (`.`) compiles to JavaScript's optional chaining (`?.`), so accessing properties on `undefined` or `null` values returns `undefined` instead of throwing an error.
526
+
527
+ ```kimchi
528
+ dec obj = { a: { b: { c: 1 } } }
529
+
530
+ print obj.a.b.c // 1
531
+ print obj.x.y.z // undefined (no error!)
532
+
533
+ // Works with arrays too
534
+ dec items = [{ name: "first" }]
535
+ print items[0].name // "first"
536
+ print items[5].name // undefined (no error!)
537
+ ```
538
+
539
+ This eliminates the need for manual null checks or the `?.` operator - every property access is automatically safe.
540
+
541
+ ### String Interpolation
542
+
543
+ Use `${expression}` inside strings for easy string interpolation:
544
+
545
+ ```kimchi
546
+ dec name = "Alice"
547
+ dec age = 30
548
+
549
+ print "Hello, ${name}!" // "Hello, Alice!"
550
+ print "${name} is ${age} years old" // "Alice is 30 years old"
551
+
552
+ // Expressions work too
553
+ dec items = [1, 2, 3]
554
+ print "Count: ${items.length}" // "Count: 3"
555
+ print "Sum: ${items.sum()}" // "Sum: 6"
556
+
557
+ // Nested expressions
558
+ dec user = { name: "Bob", score: 95 }
559
+ print "${user.name} scored ${user.score}%" // "Bob scored 95%"
560
+ ```
561
+
562
+ To include a literal `$` followed by `{`, escape it with a backslash:
563
+
564
+ ```kimchi
565
+ print "Price: \${99.99}" // "Price: ${99.99}"
566
+ ```
567
+
568
+ ### Pipe Operator
569
+
570
+ Chain function calls with the `~>` pipe operator for readable data transformations:
571
+
572
+ ```kimchi
573
+ fn double(x) { return x * 2 }
574
+ fn addOne(x) { return x + 1 }
575
+ fn square(x) { return x * x }
576
+
577
+ // Without pipe operator
578
+ dec result1 = square(addOne(double(5))) // 121
579
+
580
+ // With pipe operator - reads left to right!
581
+ dec result2 = 5 ~> double ~> addOne ~> square // 121
582
+
583
+ // Works great with array methods
584
+ dec numbers = [1, 2, 3, 4, 5]
585
+ dec processed = numbers
586
+ ~> (arr => arr.map(x => x * 2))
587
+ ~> (arr => arr.filter(x => x > 4))
588
+ ~> (arr => arr.sum()) // 24
589
+ ```
590
+
591
+ The pipe operator passes the left-hand value as the argument to the right-hand function: `a ~> f` becomes `f(a)`.
592
+
593
+ **Async Support:**
594
+
595
+ The pipe operator seamlessly handles async functions - each step is awaited automatically:
596
+
597
+ ```kimchi
598
+ async fn fetchUser(id) { return { id: id, name: "User" + id } }
599
+ async fn enrichUser(user) { return { ...user, email: user.name + "@example.com" } }
600
+
601
+ async fn main() {
602
+ // Pipe through async functions - use await on the result
603
+ dec user = await (1 ~> fetchUser ~> enrichUser)
604
+ print user.email // "User1@example.com"
605
+ }
606
+ ```
607
+
608
+ ### Memoized Functions
609
+
610
+ Use the `memo` keyword instead of `fn` to create memoized functions that cache their results:
611
+
612
+ ```kimchi
613
+ // Memoized fibonacci - exponentially faster!
614
+ memo fib(n) {
615
+ |n <= 1| => { return n }
616
+ |true| => { return fib(n - 1) + fib(n - 2) }
617
+ }
618
+
619
+ print fib(40) // Instant! (would be very slow without memoization)
620
+ ```
621
+
622
+ The cache uses a `Map` keyed by `JSON.stringify` of the arguments, so it works with any serializable arguments.
623
+
624
+ ### Error Handling
625
+
626
+ **Basic try/catch/finally:**
627
+
628
+ ```kimchi
629
+ try {
630
+ riskyOperation()
631
+ } catch(e) {
632
+ print "Error: " + e.message
633
+ } finally {
634
+ cleanup()
635
+ }
636
+ ```
637
+
638
+ **Creating typed errors with `error.create()`:**
639
+
640
+ Use `error.create(name)` to define reusable error types:
641
+
642
+ ```kimchi
643
+ // Define custom error types
644
+ dec NotFoundError = error.create("NotFoundError")
645
+ dec ValidationError = error.create("ValidationError")
646
+ dec AuthError = error.create("AuthError")
647
+
648
+ // Throw errors using your custom types
649
+ throw NotFoundError("User not found")
650
+ throw ValidationError("Email is invalid")
651
+ throw AuthError("Token expired")
652
+ ```
653
+
654
+ Each error created has:
655
+ - **`e.message`** - The error message you provide
656
+ - **`e._id`** - The error type identifier for matching with `is`
657
+ - **`e.stack`** - Full stack trace
658
+
659
+ **Catching errors by type with `is`:**
660
+
661
+ Use the `is` keyword to check if an error matches a specific type:
662
+
663
+ ```kimchi
664
+ dec NotFoundError = error.create("NotFoundError")
665
+ dec ValidationError = error.create("ValidationError")
666
+
667
+ fn fetchUser(id) {
668
+ if id == 0 {
669
+ throw NotFoundError("User ${id} not found")
670
+ }
671
+ return { id: id, name: "Alice" }
672
+ }
673
+
674
+ fn handleRequest(id) {
675
+ try {
676
+ return fetchUser(id)
677
+ } catch(e) {
678
+ |e is NotFoundError| => {
679
+ print "Not found: ${e.message}"
680
+ return null
681
+ }
682
+ |e is ValidationError| => {
683
+ print "Invalid: ${e.message}"
684
+ return null
685
+ }
686
+ |true| => {
687
+ throw e // Re-throw unknown errors
688
+ }
689
+ }
690
+ }
691
+ ```
692
+
693
+ **Using `is not` for negated type checking:**
694
+
695
+ Use `is not` to check if an error does NOT match a specific type:
696
+
697
+ ```kimchi
698
+ dec NetworkError = error.create("NetworkError")
699
+
700
+ fn handleError(e) {
701
+ |e is not NetworkError| => {
702
+ // Handle all non-network errors
703
+ print "Non-network error: ${e.message}"
704
+ return false
705
+ }
706
+ |true| => {
707
+ // Retry network errors
708
+ print "Network issue, retrying..."
709
+ return true
710
+ }
711
+ }
712
+ ```
713
+
714
+ The `is` keyword compares the `._id` property of both sides, so `e is NotFoundError` compiles to `e?._id === NotFoundError?._id`.
715
+
716
+ ### JavaScript Interop
717
+
718
+ Embed raw JavaScript code using `js { }` blocks. This provides an escape hatch for advanced JavaScript features or library usage.
719
+
720
+ **Basic JS block (no inputs):**
721
+
722
+ ```kimchi
723
+ js {
724
+ console.log("Hello from raw JavaScript!");
725
+ }
726
+ ```
727
+
728
+ **JS block with inputs from KimchiLang scope:**
729
+
730
+ Pass KimchiLang variables into the JS block explicitly:
731
+
732
+ ```kimchi
733
+ dec name = "Alice"
734
+ dec count = 5
735
+
736
+ js(name, count) {
737
+ const greeting = `Hello, ${name}! Count: ${count}`;
738
+ console.log(greeting);
739
+ }
740
+ ```
741
+
742
+ **JS block as expression (returns a value):**
743
+
744
+ ```kimchi
745
+ dec numbers = [1, 2, 3, 4, 5]
746
+
747
+ dec sum = js(numbers) {
748
+ return numbers.reduce((a, b) => a + b, 0);
749
+ }
750
+
751
+ print "Sum: ${sum}" // Sum: 15
752
+ ```
753
+
754
+ **Accessing JavaScript libraries:**
755
+
756
+ ```kimchi
757
+ dec timestamp = js {
758
+ return Date.now();
759
+ }
760
+
761
+ dec uuid = js {
762
+ return crypto.randomUUID();
763
+ }
764
+ ```
765
+
766
+ **How it works:**
767
+
768
+ JS blocks are compiled to IIFEs (Immediately Invoked Function Expressions):
769
+
770
+ ```kimchi
771
+ // KimchiLang
772
+ dec result = js(x, y) {
773
+ return x + y;
774
+ }
775
+
776
+ // Compiles to JavaScript
777
+ const result = ((x, y) => {
778
+ return x + y;
779
+ })(x, y);
780
+ ```
781
+
782
+ This ensures:
783
+ - **Isolated scope** - JS code can't accidentally modify KimchiLang variables
784
+ - **Explicit data flow** - Inputs must be declared, making dependencies clear
785
+ - **Return values** - Use `return` to pass data back to KimchiLang
786
+
787
+ ### Shell Interop
788
+
789
+ Execute shell commands using `shell { }` blocks. Shell blocks are inherently async and functions containing them are automatically made async at compile time.
790
+
791
+ **Basic shell command:**
792
+
793
+ ```kimchi
794
+ fn listFiles() {
795
+ dec result = shell { ls -la }
796
+ print result.stdout
797
+ }
798
+
799
+ listFiles() // Function is automatically async
800
+ ```
801
+
802
+ **Shell block with inputs:**
803
+
804
+ Pass KimchiLang variables into the shell command using `$variable` syntax:
805
+
806
+ ```kimchi
807
+ fn findFiles(pattern) {
808
+ dec result = shell(pattern) { find . -name "$pattern" }
809
+ return result.stdout
810
+ }
811
+
812
+ dec files = findFiles("*.km")
813
+ ```
814
+
815
+ **Return value:**
816
+
817
+ Shell blocks return an object with:
818
+ - **`stdout`** - Standard output (trimmed)
819
+ - **`stderr`** - Standard error (trimmed)
820
+ - **`exitCode`** - Exit code (0 for success)
821
+
822
+ ```kimchi
823
+ fn checkGit() {
824
+ dec result = shell { git status }
825
+
826
+ if result.exitCode == 0 {
827
+ print result.stdout
828
+ } else {
829
+ print "Error: ${result.stderr}"
830
+ }
831
+ }
832
+ ```
833
+
834
+ **Multi-line commands:**
835
+
836
+ ```kimchi
837
+ fn deploy() {
838
+ dec result = shell {
839
+ npm run build
840
+ npm run test
841
+ npm publish
842
+ }
843
+ return result
844
+ }
845
+ ```
846
+
847
+ **How it works:**
848
+
849
+ 1. Shell blocks are captured as raw text (not tokenized)
850
+ 2. Functions containing shell blocks are automatically made `async`
851
+ 3. The shell command is executed using Node.js `child_process.exec`
852
+ 4. Variables passed as inputs are interpolated into the command string
853
+
854
+ ### Static Files
855
+
856
+ Static files (`.static` extension) are data-only files for configuration, constants, and enums. They are imported like modules but contain no executable code.
857
+
858
+ **File extension:** `.static`
859
+
860
+ **Syntax:**
861
+
862
+ ```
863
+ // Primitive strings and numbers
864
+ AppName "MyApp"
865
+ Version "1.0.0"
866
+ MaxRetries 3
867
+ Timeout 5000
868
+
869
+ // Arrays: Name [value1, value2, ...]
870
+ Colors ["red", "green", "blue"]
871
+
872
+ // Objects: Name { key = value, key = value }
873
+ AppConfig {
874
+ name = "MyApp"
875
+ version = "1.0.0"
876
+ debug = true
877
+ }
878
+
879
+ // Enums: Name `MEMBER1 = value, MEMBER2 = value`
880
+ HttpStatus `OK = 200, NOT_FOUND = 404, ERROR = 500`
881
+ ```
882
+
883
+ **Multi-line declarations don't need commas:**
884
+
885
+ ```
886
+ Endpoints {
887
+ api = "https://api.example.com"
888
+ auth = "https://auth.example.com"
889
+ cdn = "https://cdn.example.com"
890
+ }
891
+ ```
892
+
893
+ **Secret values:**
894
+
895
+ Use the `secret` keyword to protect sensitive values. Secrets are masked when converted to strings:
896
+
897
+ ```
898
+ // Secret primitive
899
+ secret ApiKey "sk-1234567890abcdef"
900
+ secret InternalPort 8443
901
+
902
+ // Object with secret properties
903
+ DatabaseConfig {
904
+ host = "localhost"
905
+ port = 5432
906
+ secret username = "admin"
907
+ secret password = "super-secret-password"
908
+ }
909
+ ```
910
+
911
+ Secret values:
912
+ - Display as `********` when logged or converted to string
913
+ - Actual value accessible via `.value` property
914
+ - Protected from accidental exposure in logs and error messages
915
+
916
+ **Importing static files:**
917
+
918
+ ```kimchi
919
+ as config dep myapp.config
920
+
921
+ fn main() {
922
+ print config.AppConfig.name
923
+ print config.Colors
924
+ print config.HttpStatus.OK
925
+ }
926
+ ```
927
+
928
+ **Key differences from modules:**
929
+ - Everything is exported by default (no `expose` keyword)
930
+ - No factory function wrapper (cannot be overridden)
931
+ - Only data declarations allowed (no functions or executable code)
932
+ - Compiles to plain JavaScript exports
933
+
934
+ **Cross-file references:**
935
+
936
+ Static files can reference data from other static files using dotted paths:
937
+
938
+ ```
939
+ // In shared.static
940
+ BaseUrl "https://api.example.com"
941
+
942
+ // In config.static
943
+ Endpoints {
944
+ api = shared.BaseUrl
945
+ }
946
+ ```
947
+
948
+ ### Dependency Injection System
949
+
950
+ KimchiLang has a built-in dependency injection system using the `dep` keyword. Every module is automatically wrapped as a factory function that can accept dependency overrides.
951
+
952
+ **Basic dependency declaration:**
953
+
954
+ ```kimchi
955
+ // Declare a dependency on myapp/lib/http.km
956
+ as http dep myapp.lib.http
957
+
958
+ fn fetchData() {
959
+ return http.get("https://api.example.com/data")
960
+ }
961
+ ```
962
+
963
+ **Dependency injection for testing:**
964
+
965
+ ```kimchi
966
+ // Create a mock
967
+ dec mockHttp = {
968
+ get: (url) => { return { data: "mock" } }
969
+ }
970
+
971
+ // Inject the mock when importing
972
+ as api dep myapp.services.api({"myapp.lib.http": mockHttp})
973
+
974
+ // Now api uses the mock http client
975
+ api.fetchData() // Uses mockHttp.get instead of real http.get
976
+ ```
977
+
978
+ **How it works:**
979
+
980
+ 1. `as <alias> dep <dotted.path>` - Declares a dependency
981
+ 2. Dotted paths map to file paths: `myapp.lib.http` → `./myapp/lib/http.km`
982
+ 3. Every module exports a factory function that accepts an `_opts` object
983
+ 4. Dependencies check `_opts` first before using the real import
984
+
985
+ ### Module Arguments
986
+
987
+ Modules can declare arguments using the `arg` keyword. Arguments and dependency overrides share the same options object.
988
+
989
+ **Argument syntax:**
990
+
991
+ ```kimchi
992
+ arg timeout = 5000 // Optional arg with default value
993
+ arg clientId // Optional arg (undefined if not provided)
994
+ !arg apiKey // Required arg (throws error if missing)
995
+ ```
996
+
997
+ **Using args when importing:**
998
+
999
+ ```kimchi
1000
+ // Provide required args and override optional ones
1001
+ as api dep myapp.services.api({
1002
+ apiKey: "my-secret-key", // Required arg
1003
+ version: "v2" // Override default
1004
+ })
1005
+ ```
1006
+
1007
+ **Mixing deps and args:**
1008
+
1009
+ ```kimchi
1010
+ // Both dependency overrides and args in the same object
1011
+ as api dep myapp.services.api({
1012
+ "myapp.lib.http": mockHttp, // Dependency override (dotted path)
1013
+ apiKey: "test-key", // Required arg
1014
+ timeout: 10000 // Optional arg override
1015
+ })
1016
+ ```
1017
+
1018
+ **Example project structure:**
1019
+
1020
+ ```
1021
+ myapp/
1022
+ ├── lib/
1023
+ │ └── http.km # Low-level HTTP client
1024
+ ├── services/
1025
+ │ └── api.km # API service (depends on http)
1026
+ ├── main.km # Main app (depends on api)
1027
+ └── main_with_mock.km # Main app with mocked dependencies
1028
+ ```
1029
+
1030
+ ## CLI Commands
1031
+
1032
+ ### Module Execution
1033
+
1034
+ Run modules using dot-notation paths instead of file paths:
1035
+
1036
+ ```bash
1037
+ # Run a module by path (salesforce/client.km -> salesforce.client)
1038
+ kimchi salesforce.client
1039
+
1040
+ # Equivalent to:
1041
+ kimchi run salesforce/client.km
1042
+ ```
1043
+
1044
+ **Passing named arguments:**
1045
+
1046
+ Modules can declare arguments with `arg` and `!arg` (required). Pass them from the CLI using `--arg-name value`:
1047
+
1048
+ ```kimchi
1049
+ // api/client.km
1050
+ !arg clientId // Required argument
1051
+ arg timeout = 5000 // Optional with default
1052
+
1053
+ expose fn connect() {
1054
+ print "Connecting with ${clientId}, timeout: ${timeout}ms"
1055
+ }
1056
+
1057
+ connect()
1058
+ ```
1059
+
1060
+ ```bash
1061
+ # Pass required and optional args
1062
+ kimchi api.client --client-id ABC123 --timeout 10000
1063
+
1064
+ # Argument names convert: --client-id -> clientId (camelCase)
1065
+ ```
1066
+
1067
+ **Injecting dependencies:**
1068
+
1069
+ Override module dependencies at runtime with `--dep alias=path`:
1070
+
1071
+ ```kimchi
1072
+ // services/api.km
1073
+ as http dep lib.http // Normal dependency
1074
+
1075
+ expose fn fetch(url) {
1076
+ return http.get(url)
1077
+ }
1078
+ ```
1079
+
1080
+ ```bash
1081
+ # Inject a mock HTTP module for testing
1082
+ kimchi services.api --dep http=mocks.http
1083
+
1084
+ # Multiple dependency injections
1085
+ kimchi app.main --dep http=mocks.http --dep db=mocks.db
1086
+ ```
1087
+
1088
+ **Module help:**
1089
+
1090
+ View a module's description, arguments, and dependencies:
1091
+
1092
+ ```bash
1093
+ kimchi help api.client
1094
+ ```
1095
+
1096
+ Output:
1097
+ ```
1098
+ Module: api.client
1099
+ File: ./api/client.km
1100
+
1101
+ Description:
1102
+ API client for connecting to external services
1103
+
1104
+ Arguments:
1105
+ --client-id (required)
1106
+ --timeout [default: 5000]
1107
+
1108
+ Dependencies:
1109
+ http <- lib.http
1110
+
1111
+ Usage:
1112
+ kimchi api.client --client-id <value>
1113
+ ```
1114
+
1115
+ **Listing modules:**
1116
+
1117
+ ```bash
1118
+ # List modules in current directory
1119
+ kimchi ls
1120
+
1121
+ # List with descriptions (calls _describe() on each module)
1122
+ kimchi ls --verbose
1123
+
1124
+ # Recursive tree view
1125
+ kimchi ls ./lib --recursive --verbose
1126
+ ```
1127
+
1128
+ ### Basic Commands
1129
+
1130
+ ```bash
1131
+ # Compile a file to JavaScript
1132
+ kimchi compile app.kimchi
1133
+
1134
+ # Compile with custom output
1135
+ kimchi compile app.kimchi -o dist/app.js
1136
+
1137
+ # Run a file directly
1138
+ kimchi run app.kimchi
1139
+
1140
+ # Start interactive REPL
1141
+ kimchi repl
1142
+
1143
+ # Show help
1144
+ kimchi help
1145
+ ```
1146
+
1147
+ ### Reverse Transpiler (JavaScript to KimchiLang)
1148
+
1149
+ Convert existing JavaScript code to KimchiLang with the `convert` command:
1150
+
1151
+ ```bash
1152
+ # Convert a JavaScript file to KimchiLang
1153
+ kimchi convert app.js
1154
+
1155
+ # Convert with custom output path
1156
+ kimchi convert app.js -o src/app.km
1157
+ ```
1158
+
1159
+ The reverse transpiler handles:
1160
+ - **Variables** - `const`/`let`/`var` → `dec`
1161
+ - **Functions** - Function declarations → `fn`
1162
+ - **Classes** - Converted to factory functions (e.g., `class User` → `fn createUser()`)
1163
+ - **Imports** - ES modules and `require()` → `dep` statements
1164
+ - **Exports** - Named/default exports → `expose`
1165
+ - **console.log** → `print`
1166
+ - **Conditionals** - `if/else` → pattern matching syntax
1167
+
1168
+ **Example:**
1169
+
1170
+ ```javascript
1171
+ // input.js
1172
+ const API_URL = "https://api.example.com";
1173
+
1174
+ class UserService {
1175
+ constructor(apiKey) {
1176
+ this.apiKey = apiKey;
1177
+ }
1178
+
1179
+ getUser(id) {
1180
+ return fetch(`${API_URL}/users/${id}`);
1181
+ }
1182
+ }
1183
+
1184
+ console.log("Ready");
1185
+ ```
1186
+
1187
+ ```bash
1188
+ kimchi convert input.js
1189
+ ```
1190
+
1191
+ ```kimchi
1192
+ // output.km
1193
+ dec API_URL = "https://api.example.com"
1194
+
1195
+ // Converted from class UserService
1196
+ fn createUserService(apiKey) {
1197
+ return {
1198
+ getUser: (id) => {
1199
+ return fetch("${API_URL}/users/${id}")
1200
+ }
1201
+ }
1202
+ }
1203
+
1204
+ print "Ready"
1205
+ ```
1206
+
1207
+ ### NPM Integration
1208
+
1209
+ The `npm` subcommand runs npm and automatically converts installed packages to the `pantry/` directory:
1210
+
1211
+ ```bash
1212
+ # Install a package and convert it to pantry/
1213
+ kimchi npm install lodash
1214
+
1215
+ # Install multiple packages
1216
+ kimchi npm install axios moment
1217
+
1218
+ # Any npm command works, but only install triggers conversion
1219
+ kimchi npm update
1220
+ ```
1221
+
1222
+ After installation, packages are available in `pantry/<package>/index.km`:
1223
+
1224
+ ```kimchi
1225
+ // Use the converted package
1226
+ as lodash dep pantry.lodash
1227
+
1228
+ dec result = lodash.map([1, 2, 3], x => x * 2)
1229
+ ```
1230
+
1231
+ **How it works:**
1232
+ 1. Runs the npm command normally
1233
+ 2. Scans `node_modules/` for installed packages
1234
+ 3. Finds each package's main entry point
1235
+ 4. Converts JavaScript to KimchiLang using the reverse transpiler
1236
+ 5. Saves to `pantry/<package>/index.km`
1237
+
1238
+ **Note:** Complex packages with advanced JavaScript features may not convert perfectly. The pantry is best for simple utility libraries.
1239
+
1240
+ ## Editor Extensions
1241
+
1242
+ KimchiLang provides syntax highlighting extensions for popular editors. Extensions are located in the `editors/` directory.
1243
+
1244
+ ### Windsurf
1245
+
1246
+ The VS Code extension is fully compatible with Windsurf.
1247
+
1248
+ **Option 1: Install from VSIX (Recommended)**
1249
+
1250
+ A pre-built VSIX file is included in the repository:
1251
+
1252
+ ```bash
1253
+ # The extension is already packaged at:
1254
+ # editors/vscode/kimchilang-1.0.0.vsix
1255
+
1256
+ # To install in Windsurf:
1257
+ # 1. Open Windsurf
1258
+ # 2. Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows/Linux)
1259
+ # 3. Type "Extensions: Install from VSIX..."
1260
+ # 4. Navigate to editors/vscode/kimchilang-1.0.0.vsix
1261
+ # 5. Click Install
1262
+ # 6. Reload Windsurf when prompted
1263
+ ```
1264
+
1265
+ **Option 2: Copy to extensions folder**
1266
+
1267
+ ```bash
1268
+ # Copy the extension directly to Windsurf's extensions directory
1269
+ cp -r editors/vscode ~/.windsurf/extensions/kimchilang
1270
+
1271
+ # Restart Windsurf to activate the extension
1272
+ ```
1273
+
1274
+ **Option 3: Build and install fresh VSIX**
1275
+
1276
+ ```bash
1277
+ cd editors/vscode
1278
+ npm install -g @vscode/vsce
1279
+ vsce package
1280
+ # Then install the generated .vsix file using Option 1 steps
1281
+ ```
1282
+
1283
+ After installation, KimchiLang syntax highlighting will automatically activate for `.km`, `.kimchi`, and `.kc` files.
1284
+
1285
+ ### VS Code
1286
+
1287
+ Follow the same steps as Windsurf, but use the VS Code extensions directory:
1288
+
1289
+ ```bash
1290
+ # Option 1: Install from VSIX (same as Windsurf)
1291
+
1292
+ # Option 2: Copy to extensions folder
1293
+ cp -r editors/vscode ~/.vscode/extensions/kimchilang
1294
+ ```
1295
+
1296
+ ### Other Editors
1297
+
1298
+ See `editors/README.md` for installation instructions for:
1299
+ - **Sublime Text** - Syntax definition in `editors/sublime/`
1300
+ - **Vim/Neovim** - Syntax file and configuration
1301
+ - **Emacs** - Major mode configuration
1302
+
1303
+ ## Standard Library
1304
+
1305
+ KimchiLang includes a standard library in the `stdlib/` directory.
1306
+
1307
+ ### Logger
1308
+
1309
+ Structured JSON logging with log levels.
1310
+
1311
+ **Import:**
1312
+
1313
+ ```kimchi
1314
+ as log dep stdlib.logger
1315
+ ```
1316
+
1317
+ **Usage:**
1318
+
1319
+ ```kimchi
1320
+ log.info("Application started")
1321
+ log.debug("Debug info", { userId: 123 })
1322
+ log.warn("Warning message")
1323
+ log.error("Error occurred", { code: "ERR_001" })
1324
+ ```
1325
+
1326
+ **Log levels:** `debug`, `info`, `warn`, `error`
1327
+
1328
+ **Environment variable:** Set `LOG_LEVEL` to control minimum level (default: `info`)
1329
+
1330
+ ```bash
1331
+ LOG_LEVEL=debug kimchi myapp.main
1332
+ LOG_LEVEL=warn kimchi myapp.main
1333
+ ```
1334
+
1335
+ **Output format:** JSON with metadata
1336
+
1337
+ ```json
1338
+ {"timestamp":"2024-01-15T10:30:00.000Z","level":"info","module":"main","function":"processOrder","line":42,"message":"Order completed"}
1339
+ ```
1340
+
1341
+ **Child loggers:** Add persistent context
1342
+
1343
+ ```kimchi
1344
+ dec userLog = log.child({ userId: 456, session: "abc" })
1345
+ userLog.info("User action") // Includes userId and session in output
1346
+ ```
1347
+
1348
+ ### Bitwise
1349
+
1350
+ Bitwise operations are provided as functions rather than operators.
1351
+
1352
+ **Import:**
1353
+
1354
+ ```kimchi
1355
+ as bit dep stdlib.bitwise
1356
+ ```
1357
+
1358
+ **Functions:**
1359
+
1360
+ ```kimchi
1361
+ bit.band(a, b) // a & b (bitwise AND)
1362
+ bit.bor(a, b) // a | b (bitwise OR)
1363
+ bit.bxor(a, b) // a ^ b (bitwise XOR)
1364
+ bit.bnot(a) // ~a (bitwise NOT)
1365
+ bit.lshift(a, b) // a << b (left shift)
1366
+ bit.rshift(a, b) // a >> b (right shift, sign-propagating)
1367
+ bit.urshift(a, b) // a >>> b (unsigned right shift)
1368
+ ```
1369
+
1370
+ **Examples:**
1371
+
1372
+ ```kimchi
1373
+ as bit dep stdlib.bitwise
1374
+
1375
+ dec flags = bit.bor(0x01, 0x04) // 5
1376
+ dec masked = bit.band(flags, 0x01) // 1
1377
+ dec shifted = bit.rshift(16, 2) // 4
1378
+ ```
1379
+
1380
+ ## Package Management
1381
+
1382
+ KimchiLang has a built-in package manager for fetching external dependencies from GitHub.
1383
+
1384
+ ### project.static
1385
+
1386
+ Create a `project.static` file in your project root to declare dependencies:
1387
+
1388
+ ```
1389
+ // project.static
1390
+ name "my-app"
1391
+ version "1.0.0"
1392
+
1393
+ depend [
1394
+ "github.com/owner/repo",
1395
+ "github.com/owner/repo@v1.0.0",
1396
+ "github.com/owner/repo/path/to/module"
1397
+ ]
1398
+ ```
1399
+
1400
+ ### Installing Dependencies
1401
+
1402
+ ```bash
1403
+ # Install all dependencies from project.static
1404
+ kimchi install
1405
+
1406
+ # Remove installed dependencies
1407
+ kimchi clean
1408
+ ```
1409
+
1410
+ Dependencies are cloned to `.km_modules/` and tracked in `.km_modules/.lock.json`.
1411
+
1412
+ ### Using Installed Modules
1413
+
1414
+ Import external modules using the `@` prefix:
1415
+
1416
+ ```kimchi
1417
+ // Module installed at .km_modules/foo/bar.km
1418
+ as bar dep @foo.bar
1419
+
1420
+ // Use the imported module
1421
+ bar.doSomething()
1422
+ ```
1423
+
1424
+ The `@` prefix tells the compiler to look in `.km_modules/` instead of the local project. It also makes it clear to the reader that the module is external.
1425
+
1426
+ ### Dependency URL Format
1427
+
1428
+ | Format | Description |
1429
+ |--------|-------------|
1430
+ | `github.com/owner/repo` | Latest from main branch |
1431
+ | `github.com/owner/repo@tag` | Specific tag or branch |
1432
+ | `github.com/owner/repo/path` | Subdirectory of repo |
1433
+
1434
+ ## Testing
1435
+
1436
+ KimchiLang includes a built-in testing framework with `test`, `describe`, `expect`, and `assert`.
1437
+
1438
+ ### Test Syntax
1439
+
1440
+ **Basic test:**
1441
+
1442
+ ```kimchi
1443
+ test "addition works" {
1444
+ expect(add(2, 3)).toBe(5)
1445
+ }
1446
+ ```
1447
+
1448
+ **Grouped tests with describe:**
1449
+
1450
+ ```kimchi
1451
+ describe "Math functions" {
1452
+ test "add returns correct sum" {
1453
+ expect(add(2, 3)).toBe(5)
1454
+ }
1455
+
1456
+ test "multiply returns correct product" {
1457
+ expect(multiply(3, 4)).toBe(12)
1458
+ }
1459
+ }
1460
+ ```
1461
+
1462
+ **Assert statement:**
1463
+
1464
+ ```kimchi
1465
+ assert condition, "Error message if false"
1466
+ ```
1467
+
1468
+ ### Matchers
1469
+
1470
+ | Matcher | Description |
1471
+ |---------|-------------|
1472
+ | `toBe(value)` | Strict equality (`===`) |
1473
+ | `toEqual(value)` | Deep equality (JSON comparison) |
1474
+ | `toContain(item)` | Array/string contains item |
1475
+ | `toBeNull()` | Value is `null` |
1476
+ | `toBeTruthy()` | Value is truthy |
1477
+ | `toBeFalsy()` | Value is falsy |
1478
+ | `toBeGreaterThan(n)` | Value > n |
1479
+ | `toBeLessThan(n)` | Value < n |
1480
+ | `toHaveLength(n)` | Array/string length equals n |
1481
+ | `toMatch(regex)` | String matches regex |
1482
+ | `toThrow(message)` | Function throws error containing message |
1483
+
1484
+ ### Testing with Mocks
1485
+
1486
+ Use dependency injection to mock dependencies in tests:
1487
+
1488
+ ```kimchi
1489
+ // Create a mock
1490
+ dec mockHttp = {
1491
+ get: (url) => { status: 200, data: { id: 1, name: "Test" } }
1492
+ }
1493
+
1494
+ // Inject mock when importing module
1495
+ as userService dep myapp.user-service({
1496
+ "myapp.http-client": mockHttp
1497
+ })
1498
+
1499
+ // Test with mocked dependency
1500
+ test "getUser returns user data" {
1501
+ dec user = userService.getUser(1)
1502
+ expect(user.name).toBe("Test")
1503
+ }
1504
+ ```
1505
+
1506
+ **Run tests:**
1507
+
1508
+ ```bash
1509
+ kimchi examples.testing.math.test
1510
+ ```
1511
+
1512
+ See `examples/testing/` for complete examples.
1513
+
1514
+ ## Running Tests
1515
+
1516
+ ```bash
1517
+ node test/test.js
1518
+ ```
1519
+
1520
+ ## File Extensions
1521
+
1522
+ - `.kimchi` - Standard extension
1523
+ - `.kc` - Short extension
1524
+
1525
+ ## How It Works
1526
+
1527
+ KimchiLang uses a three-stage compilation process:
1528
+
1529
+ 1. **Lexer** (`src/lexer.js`) - Tokenizes source code into tokens
1530
+ 2. **Parser** (`src/parser.js`) - Builds an Abstract Syntax Tree (AST)
1531
+ 3. **Generator** (`src/generator.js`) - Converts AST to JavaScript
1532
+
1533
+ ## Examples
1534
+
1535
+ See the `examples/` directory for more code samples:
1536
+
1537
+ - `hello.kimchi` - Hello World
1538
+ - `basic.kimchi` - Core language features
1539
+ - `fibonacci.kimchi` - Recursive and iterative Fibonacci
1540
+ - `myapp/` - Dependency injection example with mock testing
1541
+ - `logger_example.km` - Structured JSON logging with log levels
1542
+ - `regex_match.km` - Regex pattern matching expressions
1543
+ - `testing/` - Unit testing examples with mocks
1544
+
1545
+ ## License
1546
+
1547
+ MIT