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.
- package/.github/workflows/ci.yml +66 -0
- package/README.md +1547 -0
- package/create-kimchi-app/README.md +44 -0
- package/create-kimchi-app/index.js +214 -0
- package/create-kimchi-app/package.json +22 -0
- package/editors/README.md +121 -0
- package/editors/sublime/KimchiLang.sublime-syntax +138 -0
- package/editors/vscode/README.md +90 -0
- package/editors/vscode/kimchilang-1.1.0.vsix +0 -0
- package/editors/vscode/language-configuration.json +37 -0
- package/editors/vscode/package.json +55 -0
- package/editors/vscode/src/extension.js +354 -0
- package/editors/vscode/syntaxes/kimchi.tmLanguage.json +215 -0
- package/examples/api/client.km +36 -0
- package/examples/async_pipe.km +58 -0
- package/examples/basic.kimchi +109 -0
- package/examples/cli_framework/README.md +92 -0
- package/examples/cli_framework/calculator.km +61 -0
- package/examples/cli_framework/deploy.km +126 -0
- package/examples/cli_framework/greeter.km +26 -0
- package/examples/config.static +27 -0
- package/examples/config.static.js +10 -0
- package/examples/env_test.km +37 -0
- package/examples/fibonacci.kimchi +17 -0
- package/examples/greeter.km +15 -0
- package/examples/hello.js +1 -0
- package/examples/hello.kimchi +3 -0
- package/examples/js_interop.km +42 -0
- package/examples/logger_example.km +34 -0
- package/examples/memo_fibonacci.km +17 -0
- package/examples/myapp/lib/http.js +14 -0
- package/examples/myapp/lib/http.km +16 -0
- package/examples/myapp/main.km +16 -0
- package/examples/myapp/main_with_mock.km +42 -0
- package/examples/myapp/services/api.js +18 -0
- package/examples/myapp/services/api.km +18 -0
- package/examples/new_features.kimchi +52 -0
- package/examples/project_example.static +20 -0
- package/examples/readme_examples.km +240 -0
- package/examples/reduce_pattern_match.km +85 -0
- package/examples/regex_match.km +46 -0
- package/examples/sample.js +45 -0
- package/examples/sample.km +39 -0
- package/examples/secrets.static +35 -0
- package/examples/secrets.static.js +30 -0
- package/examples/shell-example.mjs +144 -0
- package/examples/shell_example.km +19 -0
- package/examples/stdlib_test.km +22 -0
- package/examples/test_example.km +69 -0
- package/examples/testing/README.md +88 -0
- package/examples/testing/http_client.km +18 -0
- package/examples/testing/math.km +48 -0
- package/examples/testing/math.test.km +93 -0
- package/examples/testing/user_service.km +29 -0
- package/examples/testing/user_service.test.km +72 -0
- package/examples/use-config.mjs +141 -0
- package/examples/use_config.km +13 -0
- package/install.sh +59 -0
- package/package.json +29 -0
- package/pantry/acorn/index.km +1 -0
- package/pantry/is_number/index.km +1 -0
- package/pantry/is_odd/index.km +2 -0
- package/project.static +6 -0
- package/src/cli.js +1245 -0
- package/src/generator.js +1241 -0
- package/src/index.js +141 -0
- package/src/js2km.js +568 -0
- package/src/lexer.js +822 -0
- package/src/linter.js +810 -0
- package/src/package-manager.js +307 -0
- package/src/parser.js +1876 -0
- package/src/static-parser.js +500 -0
- package/src/typechecker.js +950 -0
- package/stdlib/array.km +0 -0
- package/stdlib/bitwise.km +38 -0
- package/stdlib/console.km +49 -0
- package/stdlib/date.km +97 -0
- package/stdlib/function.km +44 -0
- package/stdlib/http.km +197 -0
- package/stdlib/http.md +333 -0
- package/stdlib/index.km +26 -0
- package/stdlib/json.km +17 -0
- package/stdlib/logger.js +114 -0
- package/stdlib/logger.km +104 -0
- package/stdlib/math.km +120 -0
- package/stdlib/object.km +41 -0
- package/stdlib/promise.km +33 -0
- package/stdlib/string.km +93 -0
- package/stdlib/testing.md +265 -0
- package/test/test.js +599 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default function(_overrides = {}) {
|
|
2
|
+
function get(url) {
|
|
3
|
+
console.log(("HTTP GET: " + url));
|
|
4
|
+
return { status: 200, data: ("response from " + url) };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function post(url, body) {
|
|
8
|
+
console.log(("HTTP POST: " + url));
|
|
9
|
+
return { status: 201, data: "created" };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
return { get, post };
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// HTTP client library - a low-level dependency with configurable timeout
|
|
2
|
+
|
|
3
|
+
arg timeout = 30000
|
|
4
|
+
arg baseUrl = ""
|
|
5
|
+
|
|
6
|
+
expose fn get(url) {
|
|
7
|
+
dec fullUrl = baseUrl + url
|
|
8
|
+
print "HTTP GET: " + fullUrl + " (timeout: " + timeout + "ms)"
|
|
9
|
+
return { status: 200, data: "response from " + fullUrl }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
expose fn post(url, body) {
|
|
13
|
+
dec fullUrl = baseUrl + url
|
|
14
|
+
print "HTTP POST: " + fullUrl + " (timeout: " + timeout + "ms)"
|
|
15
|
+
return { status: 201, data: "created" }
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Main application - depends on the API service
|
|
2
|
+
// Must provide the required apiKey arg
|
|
3
|
+
|
|
4
|
+
as api dep myapp.services.api({ apiKey: "prod-key-abc123" })
|
|
5
|
+
|
|
6
|
+
fn main() {
|
|
7
|
+
print "=== Fetching users ==="
|
|
8
|
+
dec users = api.fetchUsers()
|
|
9
|
+
print users
|
|
10
|
+
|
|
11
|
+
print "=== Creating user ==="
|
|
12
|
+
dec result = api.createUser("Alice")
|
|
13
|
+
print result
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Main application with dependency injection - injects a mock HTTP client
|
|
2
|
+
// Also demonstrates passing both deps and args together
|
|
3
|
+
|
|
4
|
+
// Define a mock HTTP client for testing
|
|
5
|
+
fn mockGet(url) {
|
|
6
|
+
print "MOCK GET: " + url
|
|
7
|
+
return { status: 200, data: "mock data" }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
fn mockPost(url, body) {
|
|
11
|
+
print "MOCK POST: " + url
|
|
12
|
+
return { status: 201, data: "mock created" }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
dec mockHttp = {
|
|
16
|
+
get: mockGet,
|
|
17
|
+
post: mockPost
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Import API service with:
|
|
21
|
+
// - Mock HTTP client injected (dep override)
|
|
22
|
+
// - Required apiKey arg provided
|
|
23
|
+
// - Custom version arg provided
|
|
24
|
+
as api dep myapp.services.api({
|
|
25
|
+
"myapp.lib.http": mockHttp,
|
|
26
|
+
apiKey: "test-key-xyz789",
|
|
27
|
+
version: "v2"
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
fn main() {
|
|
31
|
+
print "=== Testing with Mock HTTP ==="
|
|
32
|
+
|
|
33
|
+
print "Fetching users (mocked):"
|
|
34
|
+
dec users = api.fetchUsers()
|
|
35
|
+
print users
|
|
36
|
+
|
|
37
|
+
print "Creating user (mocked):"
|
|
38
|
+
dec result = api.createUser("Bob")
|
|
39
|
+
print result
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
main()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import _dep_http from './myapp/lib/http.km';
|
|
2
|
+
|
|
3
|
+
export default function(_overrides = {}) {
|
|
4
|
+
const http = _overrides["myapp.lib.http"] || _dep_http();
|
|
5
|
+
|
|
6
|
+
function fetchUsers() {
|
|
7
|
+
let response = http.get("https://api.example.com/users");
|
|
8
|
+
return response.data;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function createUser(name) {
|
|
12
|
+
let response = http.post("https://api.example.com/users", { name });
|
|
13
|
+
return response.data;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
return { fetchUsers, createUser };
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// API service - depends on the HTTP library with required API key
|
|
2
|
+
|
|
3
|
+
as http dep myapp.lib.http({ baseUrl: "https://api.example.com" })
|
|
4
|
+
|
|
5
|
+
!arg apiKey
|
|
6
|
+
arg version = "v1"
|
|
7
|
+
|
|
8
|
+
expose fn fetchUsers() {
|
|
9
|
+
print "Using API key: " + apiKey + " (version: " + version + ")"
|
|
10
|
+
dec response = http.get("/" + version + "/users")
|
|
11
|
+
return response.data
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
expose fn createUser(name) {
|
|
15
|
+
print "Using API key: " + apiKey
|
|
16
|
+
dec response = http.post("/" + version + "/users", { name: name })
|
|
17
|
+
return response.data
|
|
18
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Test file for new features: String Interpolation and Pipe Operator
|
|
2
|
+
|
|
3
|
+
// ===== String Interpolation =====
|
|
4
|
+
dec name = "Alice"
|
|
5
|
+
dec age = 30
|
|
6
|
+
|
|
7
|
+
print "Hello, ${name}!"
|
|
8
|
+
print "${name} is ${age} years old"
|
|
9
|
+
|
|
10
|
+
// Expressions in interpolation
|
|
11
|
+
dec items = [1, 2, 3, 4, 5]
|
|
12
|
+
print "Count: ${items.length}"
|
|
13
|
+
print "Sum: ${items.sum()}"
|
|
14
|
+
|
|
15
|
+
// Nested object access
|
|
16
|
+
dec user = { name: "Bob", score: 95 }
|
|
17
|
+
print "${user.name} scored ${user.score}%"
|
|
18
|
+
|
|
19
|
+
// ===== Pipe Operator (~>) =====
|
|
20
|
+
fn double(x) { return x * 2 }
|
|
21
|
+
fn addOne(x) { return x + 1 }
|
|
22
|
+
fn square(x) { return x * x }
|
|
23
|
+
|
|
24
|
+
// Basic pipe chain - passes value through functions left to right
|
|
25
|
+
dec result = 5 ~> double ~> addOne ~> square
|
|
26
|
+
print "5 ~> double ~> addOne ~> square = ${result}"
|
|
27
|
+
|
|
28
|
+
// Pipe with array operations
|
|
29
|
+
fn sumArray(arr) { return arr.sum() }
|
|
30
|
+
fn doubleAll(arr) { return arr.map(x => x * 2) }
|
|
31
|
+
fn filterBig(arr) { return arr.filter(x => x > 5) }
|
|
32
|
+
|
|
33
|
+
dec numbers = [1, 2, 3, 4, 5]
|
|
34
|
+
dec processed = numbers ~> doubleAll ~> filterBig ~> sumArray
|
|
35
|
+
print "Processed array result: ${processed}"
|
|
36
|
+
|
|
37
|
+
// Combining both features
|
|
38
|
+
dec message = "The answer is ${5 ~> double ~> addOne}"
|
|
39
|
+
print message
|
|
40
|
+
|
|
41
|
+
// ===== Flow Operator (>>) =====
|
|
42
|
+
// Creates a composed function that can be called later
|
|
43
|
+
dec transform >> double addOne square
|
|
44
|
+
|
|
45
|
+
// Now call the composed function
|
|
46
|
+
dec flowResult = transform(5)
|
|
47
|
+
print "transform(5) = ${flowResult}"
|
|
48
|
+
|
|
49
|
+
// Another example with array functions
|
|
50
|
+
processArray >> doubleAll filterBig sumArray
|
|
51
|
+
dec flowArrayResult = processArray(numbers)
|
|
52
|
+
print "processArray([1,2,3,4,5]) = ${flowArrayResult}"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Example project.static file
|
|
2
|
+
// Declares external dependencies for a KimchiLang project
|
|
3
|
+
|
|
4
|
+
// Project metadata
|
|
5
|
+
name "my-awesome-app"
|
|
6
|
+
version "1.0.0"
|
|
7
|
+
description "An example KimchiLang application"
|
|
8
|
+
|
|
9
|
+
// External dependencies from GitHub
|
|
10
|
+
// Each dependency is a GitHub URL
|
|
11
|
+
depend [
|
|
12
|
+
"github.com/kimchilang/stdlib",
|
|
13
|
+
"github.com/kimchilang/http-client@v1.0.0"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
// Project configuration
|
|
17
|
+
config {
|
|
18
|
+
debug = false
|
|
19
|
+
logLevel = "info"
|
|
20
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// README Examples Validation File
|
|
2
|
+
// This file tests all KimchiLang code examples from the README
|
|
3
|
+
|
|
4
|
+
// === Quick Start ===
|
|
5
|
+
print "Hello, KimchiLang!"
|
|
6
|
+
|
|
7
|
+
fn greet(name) {
|
|
8
|
+
return "Welcome, " + name + "!"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
print greet("Developer")
|
|
12
|
+
|
|
13
|
+
// === Variables ===
|
|
14
|
+
dec name = "Alice"
|
|
15
|
+
dec PI = 3.14159
|
|
16
|
+
dec config = {
|
|
17
|
+
api: {
|
|
18
|
+
url: "https://api.example.com",
|
|
19
|
+
timeout: 5000
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Destructuring
|
|
24
|
+
dec person = { name: "Alice", age: 30, city: "NYC" }
|
|
25
|
+
dec { name: personName, age } = person
|
|
26
|
+
|
|
27
|
+
// Array destructuring
|
|
28
|
+
dec numbers = [1, 2, 3, 4, 5]
|
|
29
|
+
dec [first, second, third] = numbers
|
|
30
|
+
|
|
31
|
+
// === Module Visibility ===
|
|
32
|
+
dec internalConfig = { secret: "hidden" }
|
|
33
|
+
fn helperFn() { return "internal" }
|
|
34
|
+
|
|
35
|
+
expose dec API_VERSION = "1.0"
|
|
36
|
+
expose fn greetExposed(n) { return "Hello, " + n }
|
|
37
|
+
|
|
38
|
+
// === Functions ===
|
|
39
|
+
expose fn add(a, b) {
|
|
40
|
+
return a + b
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Default parameters
|
|
44
|
+
fn greetDefault(n = "World") {
|
|
45
|
+
return "Hello, " + n
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
print greetDefault()
|
|
49
|
+
print greetDefault("Alice")
|
|
50
|
+
|
|
51
|
+
// Rest parameters
|
|
52
|
+
fn sum(...nums) {
|
|
53
|
+
return nums.reduce((acc, n) => acc + n, 0)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
print sum(1, 2, 3, 4, 5)
|
|
57
|
+
|
|
58
|
+
// Combined
|
|
59
|
+
fn log(prefix, separator = ": ", ...messages) {
|
|
60
|
+
return prefix + separator + messages.join(", ")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// === Enums ===
|
|
64
|
+
enum Color {
|
|
65
|
+
Red,
|
|
66
|
+
Green,
|
|
67
|
+
Blue
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
print Color.Red
|
|
71
|
+
print Color.Green
|
|
72
|
+
|
|
73
|
+
enum HttpStatus {
|
|
74
|
+
OK = 200,
|
|
75
|
+
NotFound = 404,
|
|
76
|
+
ServerError = 500
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
enum Priority {
|
|
80
|
+
Low,
|
|
81
|
+
Medium,
|
|
82
|
+
High = 10,
|
|
83
|
+
Critical
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fn getStatusMessage(status) {
|
|
87
|
+
|status == HttpStatus.OK| => { return "Success" }
|
|
88
|
+
|status == HttpStatus.NotFound| => { return "Not Found" }
|
|
89
|
+
|true| => { return "Unknown" }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
print getStatusMessage(200)
|
|
93
|
+
|
|
94
|
+
// === Arrow Functions ===
|
|
95
|
+
dec double = x => x * 2
|
|
96
|
+
dec addArrow = (a, b) => a + b
|
|
97
|
+
|
|
98
|
+
dec process = (x) => {
|
|
99
|
+
dec result = x * 2
|
|
100
|
+
return result + 1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
dec numbersArr = [1, 2, 3, 4, 5]
|
|
104
|
+
dec doubled = numbersArr.map(x => x * 2)
|
|
105
|
+
dec sumArr = numbersArr.reduce((acc, n) => acc + n, 0)
|
|
106
|
+
|
|
107
|
+
// === Control Flow ===
|
|
108
|
+
dec score = 85
|
|
109
|
+
if score >= 90 {
|
|
110
|
+
print "A"
|
|
111
|
+
} elif score >= 80 {
|
|
112
|
+
print "B"
|
|
113
|
+
} else {
|
|
114
|
+
print "C"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// For loop
|
|
118
|
+
dec items = ["a", "b", "c"]
|
|
119
|
+
for item in items {
|
|
120
|
+
print item
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Range expressions
|
|
124
|
+
for i in 0..5 {
|
|
125
|
+
print i
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// === Flow Operator ===
|
|
129
|
+
fn addOne(x) { return x + 1 }
|
|
130
|
+
fn doubleNum(x) { return x * 2 }
|
|
131
|
+
fn square(x) { return x * x }
|
|
132
|
+
|
|
133
|
+
transform >> addOne doubleNum square
|
|
134
|
+
dec flowResult = transform(5)
|
|
135
|
+
print "Flow result: ${flowResult}"
|
|
136
|
+
|
|
137
|
+
// === Pattern Matching ===
|
|
138
|
+
fn handleStatus(status) {
|
|
139
|
+
|status == 200| => { print "OK" }
|
|
140
|
+
|status == 404| => { print "Not Found" }
|
|
141
|
+
|status == 500| => { print "Server Error" }
|
|
142
|
+
|true| => { print "Unknown" }
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
handleStatus(200)
|
|
146
|
+
|
|
147
|
+
// === Arrays & Objects ===
|
|
148
|
+
dec nums = [1, 2, 3, 4, 5]
|
|
149
|
+
dec personObj = {
|
|
150
|
+
name: "Bob",
|
|
151
|
+
age: 30
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
dec more = [...nums, 6, 7, 8]
|
|
155
|
+
dec updated = { ...personObj, age: 31 }
|
|
156
|
+
|
|
157
|
+
// === Safe Member Access ===
|
|
158
|
+
dec obj = { a: { b: { c: 1 } } }
|
|
159
|
+
print obj.a.b.c
|
|
160
|
+
|
|
161
|
+
// === String Interpolation ===
|
|
162
|
+
dec userName = "Alice"
|
|
163
|
+
dec userAge = 30
|
|
164
|
+
|
|
165
|
+
print "Hello, ${userName}!"
|
|
166
|
+
print "${userName} is ${userAge} years old"
|
|
167
|
+
|
|
168
|
+
dec itemsCount = [1, 2, 3]
|
|
169
|
+
print "Count: ${itemsCount.length}"
|
|
170
|
+
|
|
171
|
+
// === Pipe Operator ===
|
|
172
|
+
dec pipeResult1 = square(addOne(doubleNum(5)))
|
|
173
|
+
dec pipeResult2 = 5 ~> doubleNum ~> addOne ~> square
|
|
174
|
+
print "Pipe result: ${pipeResult2}"
|
|
175
|
+
|
|
176
|
+
// === Memoized Functions ===
|
|
177
|
+
memo fib(n) {
|
|
178
|
+
|n <= 1| => { return n }
|
|
179
|
+
|true| => { return fib(n - 1) + fib(n - 2) }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
print "fib(10) = ${fib(10)}"
|
|
183
|
+
|
|
184
|
+
// === Error Handling ===
|
|
185
|
+
dec NotFoundError = error.create("NotFoundError")
|
|
186
|
+
dec ValidationError = error.create("ValidationError")
|
|
187
|
+
|
|
188
|
+
fn fetchUser(id) {
|
|
189
|
+
if id == 0 {
|
|
190
|
+
throw NotFoundError("User ${id} not found")
|
|
191
|
+
}
|
|
192
|
+
return { id: id, name: "Alice" }
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
fn handleRequest(id) {
|
|
196
|
+
try {
|
|
197
|
+
return fetchUser(id)
|
|
198
|
+
} catch(e) {
|
|
199
|
+
|e is NotFoundError| => {
|
|
200
|
+
print "Not found: ${e.message}"
|
|
201
|
+
return null
|
|
202
|
+
}
|
|
203
|
+
|e is ValidationError| => {
|
|
204
|
+
print "Invalid: ${e.message}"
|
|
205
|
+
return null
|
|
206
|
+
}
|
|
207
|
+
|true| => {
|
|
208
|
+
throw e
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
dec user = handleRequest(1)
|
|
214
|
+
print "User: ${user.name}"
|
|
215
|
+
|
|
216
|
+
// === JavaScript Interop ===
|
|
217
|
+
js {
|
|
218
|
+
console.log("Hello from raw JavaScript!");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
dec jsName = "Alice"
|
|
222
|
+
dec jsCount = 5
|
|
223
|
+
|
|
224
|
+
js(jsName, jsCount) {
|
|
225
|
+
const greeting = `Hello, ${jsName}! Count: ${jsCount}`;
|
|
226
|
+
console.log(greeting);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
dec jsNumbers = [1, 2, 3, 4, 5]
|
|
230
|
+
dec jsSum = js(jsNumbers) {
|
|
231
|
+
return jsNumbers.reduce((a, b) => a + b, 0);
|
|
232
|
+
}
|
|
233
|
+
print "JS Sum: ${jsSum}"
|
|
234
|
+
|
|
235
|
+
dec timestamp = js {
|
|
236
|
+
return Date.now();
|
|
237
|
+
}
|
|
238
|
+
print "Timestamp: ${timestamp}"
|
|
239
|
+
|
|
240
|
+
print "All README examples validated successfully!"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Pattern matching in Array.reduce callback
|
|
2
|
+
// Demonstrates using pattern matching to categorize and accumulate values
|
|
3
|
+
|
|
4
|
+
dec transactions = [
|
|
5
|
+
{ type: "credit", amount: 100 },
|
|
6
|
+
{ type: "debit", amount: 50 },
|
|
7
|
+
{ type: "credit", amount: 200 },
|
|
8
|
+
{ type: "debit", amount: 75 },
|
|
9
|
+
{ type: "refund", amount: 25 }
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
// Define reducer function with pattern matching
|
|
13
|
+
fn transactionReducer(acc, tx) {
|
|
14
|
+
|tx.type == "credit"| => {
|
|
15
|
+
return acc + tx.amount
|
|
16
|
+
}
|
|
17
|
+
|tx.type == "debit"| => {
|
|
18
|
+
return acc - tx.amount
|
|
19
|
+
}
|
|
20
|
+
|tx.type == "refund"| => {
|
|
21
|
+
return acc + tx.amount
|
|
22
|
+
}
|
|
23
|
+
|true| => {
|
|
24
|
+
return acc
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
dec balance = transactions.reduce(transactionReducer, 0)
|
|
29
|
+
print "Final balance: $${balance}"
|
|
30
|
+
|
|
31
|
+
// Another example: grouping items by category
|
|
32
|
+
dec items = [
|
|
33
|
+
{ name: "apple", category: "fruit" },
|
|
34
|
+
{ name: "carrot", category: "vegetable" },
|
|
35
|
+
{ name: "banana", category: "fruit" },
|
|
36
|
+
{ name: "broccoli", category: "vegetable" },
|
|
37
|
+
{ name: "orange", category: "fruit" }
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
fn groupReducer(acc, item) {
|
|
41
|
+
|item.category == "fruit"| => {
|
|
42
|
+
return {
|
|
43
|
+
fruits: [...acc.fruits, item.name],
|
|
44
|
+
vegetables: acc.vegetables
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|item.category == "vegetable"| => {
|
|
48
|
+
return {
|
|
49
|
+
fruits: acc.fruits,
|
|
50
|
+
vegetables: [...acc.vegetables, item.name]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|true| => {
|
|
54
|
+
return acc
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
dec grouped = items.reduce(groupReducer, { fruits: [], vegetables: [] })
|
|
59
|
+
|
|
60
|
+
print "\nGrouped items:"
|
|
61
|
+
print "Fruits: ${grouped.fruits.join(", ")}"
|
|
62
|
+
print "Vegetables: ${grouped.vegetables.join(", ")}"
|
|
63
|
+
|
|
64
|
+
// Example: state machine with pattern matching in arrow function
|
|
65
|
+
dec events = ["start", "pause", "resume", "stop", "start"]
|
|
66
|
+
|
|
67
|
+
dec finalState = events.reduce((state, event) => {
|
|
68
|
+
|event == "start"| => {
|
|
69
|
+
return "running"
|
|
70
|
+
}
|
|
71
|
+
|event == "pause" and state == "running"| => {
|
|
72
|
+
return "paused"
|
|
73
|
+
}
|
|
74
|
+
|event == "resume" and state == "paused"| => {
|
|
75
|
+
return "running"
|
|
76
|
+
}
|
|
77
|
+
|event == "stop"| => {
|
|
78
|
+
return "stopped"
|
|
79
|
+
}
|
|
80
|
+
|true| => {
|
|
81
|
+
return state
|
|
82
|
+
}
|
|
83
|
+
}, "idle")
|
|
84
|
+
|
|
85
|
+
print "\nFinal state: ${finalState}"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Regex Pattern Matching Example
|
|
2
|
+
// Demonstrates two syntaxes:
|
|
3
|
+
// 1. Simple match: expr ~ /regex/ - returns the matched string or undefined
|
|
4
|
+
// 2. Match with body: expr ~ /regex/ => { return value } - returns the body result
|
|
5
|
+
|
|
6
|
+
// Simple match - returns the matched portion
|
|
7
|
+
dec input = "hello world 123"
|
|
8
|
+
dec matched = input ~ /hello/
|
|
9
|
+
print "Simple match result: ${matched}"
|
|
10
|
+
|
|
11
|
+
// Match with transformation - returns body result
|
|
12
|
+
dec transformed = input ~ /(\w+) (\w+)/ => { return $match[2] }
|
|
13
|
+
print "Transformed (second word): ${transformed}"
|
|
14
|
+
|
|
15
|
+
// Extract numbers from string
|
|
16
|
+
dec numbers = "Price: $42.99" ~ /\d+\.\d+/
|
|
17
|
+
print "Extracted number: ${numbers}"
|
|
18
|
+
|
|
19
|
+
// Match with body for complex transformation
|
|
20
|
+
dec greeting = "Hello, John!" ~ /Hello, (\w+)!/ => {
|
|
21
|
+
return "Welcome, ${$match[1]}!"
|
|
22
|
+
}
|
|
23
|
+
print greeting
|
|
24
|
+
|
|
25
|
+
// Regex literals can also be used directly in expressions
|
|
26
|
+
dec emailPattern = /^[\w.-]+@[\w.-]+\.\w+$/
|
|
27
|
+
dec phonePattern = /^\d{3}-\d{3}-\d{4}$/
|
|
28
|
+
|
|
29
|
+
fn validateEmail(email) {
|
|
30
|
+
return emailPattern.test(email)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
fn validatePhone(phone) {
|
|
34
|
+
return phonePattern.test(phone)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
print ""
|
|
38
|
+
print "=== Validation Examples ==="
|
|
39
|
+
print "Is 'test@example.com' a valid email? ${validateEmail('test@example.com')}"
|
|
40
|
+
print "Is '555-123-4567' a valid phone? ${validatePhone('555-123-4567')}"
|
|
41
|
+
|
|
42
|
+
// Conditional based on match result
|
|
43
|
+
dec logLine = "ERROR: Connection failed"
|
|
44
|
+
dec level = logLine ~ /^(ERROR|WARN|INFO|DEBUG)/
|
|
45
|
+
print ""
|
|
46
|
+
print "Log level: ${level}"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Sample JavaScript file to test JS to KimchiLang conversion
|
|
2
|
+
|
|
3
|
+
const API_URL = "https://api.example.com";
|
|
4
|
+
|
|
5
|
+
function add(a, b) {
|
|
6
|
+
return a + b;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function greet(name) {
|
|
10
|
+
console.log("Hello, " + name);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class UserService {
|
|
14
|
+
constructor(apiKey) {
|
|
15
|
+
this.apiKey = apiKey;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getUser(id) {
|
|
19
|
+
return this.apiKey + "/users/" + id;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
createUser(name, email) {
|
|
23
|
+
console.log("Creating user: " + name);
|
|
24
|
+
return { name, email };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const numbers = [1, 2, 3, 4, 5];
|
|
29
|
+
const doubled = numbers.map(x => x * 2);
|
|
30
|
+
|
|
31
|
+
function processStatus(status) {
|
|
32
|
+
if (status === 200) {
|
|
33
|
+
console.log("OK");
|
|
34
|
+
} else if (status === 404) {
|
|
35
|
+
console.log("Not Found");
|
|
36
|
+
} else {
|
|
37
|
+
console.log("Unknown");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const num of numbers) {
|
|
42
|
+
console.log(num);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { add, greet, UserService };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
dec API_URL = "https://api.example.com"
|
|
2
|
+
fn add(a, b) {
|
|
3
|
+
return a + b
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
fn greet(name) {
|
|
7
|
+
print "Hello, " + name
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Converted from class UserService
|
|
11
|
+
fn createUserService(apiKey) {
|
|
12
|
+
return {
|
|
13
|
+
getUser: (id) => {
|
|
14
|
+
return "${apiKey}/users/${id}"
|
|
15
|
+
},
|
|
16
|
+
createUser: (name, email) => {
|
|
17
|
+
print "Creating user: ${name}"
|
|
18
|
+
return { name, email }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
dec numbers = [1, 2, 3, 4, 5]
|
|
24
|
+
dec doubled = numbers.map(x => x * 2)
|
|
25
|
+
fn processStatus(status) {
|
|
26
|
+
|status == 200| => {
|
|
27
|
+
print "OK"
|
|
28
|
+
}
|
|
29
|
+
|status == 404| => {
|
|
30
|
+
print "Not Found"
|
|
31
|
+
}
|
|
32
|
+
|true| => {
|
|
33
|
+
print "Unknown"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for num in numbers {
|
|
38
|
+
print num
|
|
39
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Example static file with primitives and secrets
|
|
2
|
+
|
|
3
|
+
// String primitives
|
|
4
|
+
AppName "MySecureApp"
|
|
5
|
+
Version "1.0.0"
|
|
6
|
+
|
|
7
|
+
// Number primitives
|
|
8
|
+
MaxConnections 100
|
|
9
|
+
Timeout 5000
|
|
10
|
+
|
|
11
|
+
// Boolean primitive
|
|
12
|
+
DebugMode false
|
|
13
|
+
|
|
14
|
+
// Secret string primitive
|
|
15
|
+
secret ApiKey "sk-1234567890abcdef"
|
|
16
|
+
|
|
17
|
+
// Secret number (e.g., a port that should be hidden)
|
|
18
|
+
secret InternalPort 8443
|
|
19
|
+
|
|
20
|
+
// Object with secret properties
|
|
21
|
+
DatabaseConfig {
|
|
22
|
+
host = "localhost"
|
|
23
|
+
port = 5432
|
|
24
|
+
database = "myapp"
|
|
25
|
+
secret username = "admin"
|
|
26
|
+
secret password = "super-secret-password"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Mixed object with some secrets
|
|
30
|
+
ServiceConfig {
|
|
31
|
+
name = "api-service"
|
|
32
|
+
url = "https://api.example.com"
|
|
33
|
+
secret token = "bearer-token-12345"
|
|
34
|
+
retries = 3
|
|
35
|
+
}
|