arc-lang 0.6.2 → 0.6.4

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 (48) hide show
  1. package/README.md +65 -130
  2. package/dist/ast.d.ts +30 -2
  3. package/dist/build.js +1 -1
  4. package/dist/formatter.js +15 -3
  5. package/dist/index.js +104 -0
  6. package/dist/interpreter.js +130 -17
  7. package/dist/lexer.d.ts +41 -37
  8. package/dist/lexer.js +47 -39
  9. package/dist/linter.js +18 -0
  10. package/dist/modules.js +5 -1
  11. package/dist/parser.d.ts +2 -0
  12. package/dist/parser.js +91 -11
  13. package/dist/repl.js +66 -1
  14. package/dist/version.d.ts +1 -1
  15. package/dist/version.js +1 -1
  16. package/package.json +4 -2
  17. package/stdlib/API_DESIGN.md +357 -0
  18. package/stdlib/ASYNC_DESIGN.md +815 -0
  19. package/stdlib/EXAMPLES.md +710 -0
  20. package/stdlib/MODULES.md +854 -0
  21. package/stdlib/README.md +64 -0
  22. package/stdlib/collections.arc +140 -0
  23. package/stdlib/crypto.arc +62 -0
  24. package/stdlib/csv.arc +40 -0
  25. package/stdlib/datetime.arc +75 -0
  26. package/stdlib/embed.arc +42 -0
  27. package/stdlib/env.arc +10 -0
  28. package/stdlib/error.arc +36 -0
  29. package/stdlib/html.arc +30 -0
  30. package/stdlib/http.arc +43 -0
  31. package/stdlib/io.arc +28 -0
  32. package/stdlib/json.arc +204 -0
  33. package/stdlib/llm.arc +193 -0
  34. package/stdlib/log.arc +20 -0
  35. package/stdlib/map.arc +72 -0
  36. package/stdlib/math.arc +133 -0
  37. package/stdlib/net.arc +17 -0
  38. package/stdlib/os.arc +81 -0
  39. package/stdlib/path.arc +11 -0
  40. package/stdlib/prompt.arc +49 -0
  41. package/stdlib/regex.arc +59 -0
  42. package/stdlib/result.arc +50 -0
  43. package/stdlib/store.arc +62 -0
  44. package/stdlib/strings.arc +44 -0
  45. package/stdlib/test.arc +61 -0
  46. package/stdlib/time.arc +19 -0
  47. package/stdlib/toml.arc +10 -0
  48. package/stdlib/yaml.arc +10 -0
package/dist/repl.js CHANGED
@@ -16,6 +16,8 @@ const useHandler = createUseHandler(process.cwd() + "/repl.arc");
16
16
  function printHelp() {
17
17
  console.log(`${CYAN}Arc REPL Commands:${RESET}`);
18
18
  console.log(` ${YELLOW}:help${RESET} Show this help message`);
19
+ console.log(` ${YELLOW}:builtins${RESET} List all built-in functions`);
20
+ console.log(` ${YELLOW}:modules${RESET} List available stdlib modules`);
19
21
  console.log(` ${YELLOW}:ast${RESET} Toggle AST display before execution`);
20
22
  console.log(` ${YELLOW}:reset${RESET} Clear all variables and state`);
21
23
  console.log(` ${YELLOW}:load <file>${RESET} Load and execute an Arc file`);
@@ -23,6 +25,56 @@ function printHelp() {
23
25
  console.log(` ${YELLOW}Ctrl+C${RESET} Exit the REPL`);
24
26
  console.log();
25
27
  console.log(` Multi-line: end a line with { to start a block`);
28
+ console.log(` Comments: # or // (both work)`);
29
+ console.log(` Docs: https://arclang.dev | See CHEATSHEET.md`);
30
+ }
31
+ function printBuiltins() {
32
+ console.log(`${CYAN}Built-in Functions:${RESET}`);
33
+ console.log();
34
+ console.log(`${YELLOW}I/O:${RESET} print(...values)`);
35
+ console.log(`${YELLOW}Type Convert:${RESET} int(v) float(v) str(v) bool(v) type_of(v)`);
36
+ console.log(`${YELLOW}Strings:${RESET} len trim upper lower split join replace`);
37
+ console.log(` contains starts ends repeat chars slice`);
38
+ console.log(` index_of ord chr char_at`);
39
+ console.log(`${YELLOW}Lists:${RESET} map filter reduce fold find any all sort`);
40
+ console.log(` head tail last reverse take drop flat`);
41
+ console.log(` zip enumerate push concat sum range`);
42
+ console.log(`${YELLOW}Maps:${RESET} keys values entries len`);
43
+ console.log(`${YELLOW}Math:${RESET} abs min max round`);
44
+ console.log(`${YELLOW}Other:${RESET} assert time_ms to_string`);
45
+ console.log();
46
+ console.log(`${CYAN}Operators:${RESET} + - * / % ** ++ == != < > <= >= and or not |> .. ?.`);
47
+ console.log(`${CYAN}Syntax:${RESET} "string {expr}" * (string repeat) # // (comments) try/catch`);
48
+ }
49
+ function printModules() {
50
+ console.log(`${CYAN}Standard Library Modules:${RESET} (import with: use <module>)`);
51
+ console.log();
52
+ console.log(` ${YELLOW}math${RESET} sqrt, pow, ceil, floor, clamp, PI, E, sin, cos, log`);
53
+ console.log(` ${YELLOW}strings${RESET} pad_left, pad_right, capitalize, words`);
54
+ console.log(` ${YELLOW}collections${RESET} group_by, chunk, flatten, zip_with, partition, sort_by, unique`);
55
+ console.log(` ${YELLOW}map${RESET} merge, map_values, filter_map, from_pairs, pick, omit`);
56
+ console.log(` ${YELLOW}io${RESET} read_file, write_file, read_lines, exists, append`);
57
+ console.log(` ${YELLOW}http${RESET} get, post, put, delete — real HTTP requests`);
58
+ console.log(` ${YELLOW}json${RESET} to_json, from_json, pretty, get_path`);
59
+ console.log(` ${YELLOW}csv${RESET} parse_csv, to_csv, parse_csv_headers`);
60
+ console.log(` ${YELLOW}regex${RESET} match, find, test, replace, split, capture`);
61
+ console.log(` ${YELLOW}datetime${RESET} now, today, parse, format, add_days, diff_days`);
62
+ console.log(` ${YELLOW}os${RESET} cwd, list_dir, mkdir, exec, platform, env`);
63
+ console.log(` ${YELLOW}env${RESET} get, set, has, all — environment variables`);
64
+ console.log(` ${YELLOW}crypto${RESET} sha256, sha512, hmac_sha256, uuid, random_bytes`);
65
+ console.log(` ${YELLOW}error${RESET} try_catch, try_finally, throw, retry, assert`);
66
+ console.log(` ${YELLOW}result${RESET} ok, err, is_ok, unwrap, map_result, try_fn`);
67
+ console.log(` ${YELLOW}net${RESET} ws_connect, tcp_connect, dns_lookup, base64_encode`);
68
+ console.log(` ${YELLOW}yaml${RESET} parse, stringify`);
69
+ console.log(` ${YELLOW}toml${RESET} parse, stringify`);
70
+ console.log(` ${YELLOW}html${RESET} parse, create_element, to_html`);
71
+ console.log(` ${YELLOW}path${RESET} join, dirname, basename, extname`);
72
+ console.log(` ${YELLOW}log${RESET} info, warn, error, debug`);
73
+ console.log(` ${YELLOW}store${RESET} get, set, delete — persistent key-value storage`);
74
+ console.log(` ${YELLOW}test${RESET} describe, it, expect_eq, run_tests`);
75
+ console.log(` ${YELLOW}prompt${RESET} template, count_tokens, window`);
76
+ console.log(` ${YELLOW}embed${RESET} similarity, cosine, search`);
77
+ console.log(` ${YELLOW}llm${RESET} chat, complete — multi-provider LLM API`);
26
78
  }
27
79
  function execute(source) {
28
80
  try {
@@ -38,6 +90,9 @@ function execute(source) {
38
90
  }
39
91
  catch (e) {
40
92
  console.log(`${RED}Error: ${e.message}${RESET}`);
93
+ if (e.suggestion) {
94
+ console.log(`${YELLOW}hint${RESET}: ${e.suggestion}`);
95
+ }
41
96
  }
42
97
  }
43
98
  function main() {
@@ -46,7 +101,7 @@ function main() {
46
101
  output: process.stdout,
47
102
  prompt: "arc> ",
48
103
  });
49
- console.log(`${CYAN}Arc REPL v0.1.0${RESET} — Type ${YELLOW}:help${RESET} for commands`);
104
+ console.log(`${CYAN}Arc REPL v0.6.4${RESET} — Type ${YELLOW}:help${RESET} for commands, ${YELLOW}:builtins${RESET} for functions`);
50
105
  rl.prompt();
51
106
  let buffer = "";
52
107
  let braceDepth = 0;
@@ -63,6 +118,16 @@ function main() {
63
118
  rl.prompt();
64
119
  return;
65
120
  }
121
+ if (trimmed === ":builtins" || trimmed === ":b") {
122
+ printBuiltins();
123
+ rl.prompt();
124
+ return;
125
+ }
126
+ if (trimmed === ":modules" || trimmed === ":m") {
127
+ printModules();
128
+ rl.prompt();
129
+ return;
130
+ }
66
131
  if (trimmed === ":ast") {
67
132
  showAst = !showAst;
68
133
  console.log(`AST display: ${showAst ? "ON" : "OFF"}`);
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const ARC_VERSION = "0.6.2";
1
+ export declare const ARC_VERSION = "0.6.4";
2
2
  export declare const ARC_BUILD_DATE: string;
3
3
  export declare const ARC_PLATFORM: string;
4
4
  /** Print version info */
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Arc Version System
2
- export const ARC_VERSION = "0.6.2";
2
+ export const ARC_VERSION = "0.6.4";
3
3
  export const ARC_BUILD_DATE = new Date().toISOString().split("T")[0];
4
4
  export const ARC_PLATFORM = `${process.platform}-${process.arch}`;
5
5
  /** Print version info */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arc-lang",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Arc ⚡ — A programming language designed by AI agents, for AI agents. 27-63% fewer tokens than JavaScript.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,12 +9,14 @@
9
9
  "main": "./dist/index.js",
10
10
  "files": [
11
11
  "dist/",
12
+ "stdlib/",
12
13
  "README.md",
13
14
  "LICENSE"
14
15
  ],
15
16
  "scripts": {
16
17
  "build": "tsc",
17
- "prepublishOnly": "tsc",
18
+ "copy-stdlib": "node -e \"const fs=require('fs');const p=require('path');function cp(s,d){fs.mkdirSync(d,{recursive:true});for(const f of fs.readdirSync(s)){const sp=p.join(s,f),dp=p.join(d,f);fs.statSync(sp).isDirectory()?cp(sp,dp):fs.copyFileSync(sp,dp)}}cp(p.join(__dirname,'..','stdlib'),p.join(__dirname,'stdlib'))\"",
19
+ "prepublishOnly": "npm run copy-stdlib && tsc",
18
20
  "run": "tsx src/index.ts run",
19
21
  "parse": "tsx src/index.ts parse"
20
22
  },
@@ -0,0 +1,357 @@
1
+ # Arc Standard Library API Design
2
+
3
+ ## Design Principles
4
+
5
+ 1. **Token-minimal APIs** — Short function names, no unnecessary prefixes
6
+ 2. **Convention over configuration** — Sensible defaults, override when needed
7
+ 3. **Composable** — All functions work with `|>` pipeline
8
+ 4. **Consistent** — Same patterns across all modules
9
+ 5. **Zero-import common ops** — `print`, `len`, `map`, `filter` are always available (prelude)
10
+
11
+ ---
12
+
13
+ ## Prelude (Always Available)
14
+
15
+ These functions require no `use` statement:
16
+
17
+ ```arc
18
+ # I/O
19
+ print(value) # Print to stdout
20
+ read(path) -> String # Read file contents
21
+ write(path, data) # Write to file
22
+
23
+ # Collections
24
+ len(collection) -> Int
25
+ map(collection, fn) -> [T]
26
+ filter(collection, fn) -> [T]
27
+ reduce(collection, init, fn) -> T
28
+ sort(collection, [key_fn]) -> [T]
29
+ take(collection, n) -> [T]
30
+ drop(collection, n) -> [T]
31
+ find(collection, fn) -> Option<T>
32
+ any(collection, fn) -> Bool
33
+ all(collection, fn) -> Bool
34
+ sum(collection) -> Number
35
+ flat(collection) -> [T]
36
+ zip(a, b) -> [(A, B)]
37
+ enumerate(collection) -> [(Int, T)]
38
+
39
+ # Strings
40
+ trim(s) -> String
41
+ split(s, delim) -> [String]
42
+ join(collection, delim) -> String
43
+ upper(s) -> String
44
+ lower(s) -> String
45
+ replace(s, from, to) -> String
46
+ contains(s, substr) -> Bool
47
+ starts(s, prefix) -> Bool
48
+ ends(s, suffix) -> Bool
49
+
50
+ # Type conversion
51
+ int(value) -> Int
52
+ float(value) -> Float
53
+ str(value) -> String
54
+ bool(value) -> Bool
55
+
56
+ # Math
57
+ min(a, b) -> Number
58
+ max(a, b) -> Number
59
+ abs(x) -> Number
60
+ round(x, [decimals]) -> Number
61
+ ```
62
+
63
+ **Rationale:** These ~40 functions cover ~80% of typical agent operations. No imports needed = fewer tokens per program. Names are short (3-5 chars) and unambiguous.
64
+
65
+ ---
66
+
67
+ ## Module: `std/collections`
68
+
69
+ ```arc
70
+ use std/collections: Set, Stack, Queue, deque
71
+
72
+ # Sets
73
+ let s = Set([1, 2, 3])
74
+ s |> add(4) # {1, 2, 3, 4}
75
+ s |> has(2) # true
76
+ s |> union(Set([3, 4, 5])) # {1, 2, 3, 4, 5}
77
+ s |> intersect(Set([2, 3])) # {2, 3}
78
+ s |> diff(Set([2])) # {1, 3}
79
+
80
+ # Stack (LIFO)
81
+ let st = Stack()
82
+ st |> push(1) |> push(2)
83
+ st |> pop # (2, Stack([1]))
84
+
85
+ # Queue (FIFO)
86
+ let q = Queue()
87
+ q |> enq(1) |> enq(2)
88
+ q |> deq # (1, Queue([2]))
89
+
90
+ # Sorted map
91
+ use std/collections: SortedMap
92
+ let sm = SortedMap({a: 1, c: 3, b: 2})
93
+ sm |> keys # ["a", "b", "c"]
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Module: `std/math`
99
+
100
+ ```arc
101
+ use std/math: pi, e, sin, cos, tan, log, sqrt, pow, floor, ceil, clamp, rand
102
+
103
+ sqrt(16) # 4.0
104
+ clamp(15, 0, 10) # 10
105
+ rand() # 0.0..1.0
106
+ rand(1, 100) # random int 1-100
107
+ sin(pi / 2) # 1.0
108
+ log(e) # 1.0
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Module: `std/http`
114
+
115
+ ```arc
116
+ use std/http: serve, request
117
+
118
+ # Server
119
+ serve 3000 {
120
+ GET "/" => fn(req) => "Hello!"
121
+
122
+ GET "/users/:id" => fn(req) {
123
+ @db("SELECT * FROM users WHERE id = {req.params.id}")
124
+ }
125
+
126
+ POST "/users" => fn(req) {
127
+ @db("INSERT INTO users VALUES ({req.body.name}, {req.body.email})")
128
+ }
129
+
130
+ # Middleware
131
+ before => fn(req) {
132
+ log("{req.method} {req.path}")
133
+ req
134
+ }
135
+ }
136
+
137
+ # Client (usually via @GET/@POST, but configurable requests available)
138
+ let resp = request({
139
+ url: "https://api.example.com/data",
140
+ method: "GET",
141
+ headers: {Authorization: "Bearer {token}"},
142
+ timeout: 5000
143
+ })
144
+ ```
145
+
146
+ **Comparison — Express.js equivalent:**
147
+
148
+ ```javascript
149
+ // JavaScript: ~50 tokens for basic server setup
150
+ const express = require('express');
151
+ const app = express();
152
+ app.use(express.json());
153
+ app.get('/', (req, res) => res.send('Hello!'));
154
+ app.get('/users/:id', async (req, res) => { ... });
155
+ app.post('/users', async (req, res) => { ... });
156
+ app.listen(3000);
157
+ ```
158
+
159
+ ```arc
160
+ # Arc: ~20 tokens for same functionality
161
+ serve 3000 {
162
+ GET "/" => fn(req) => "Hello!"
163
+ GET "/users/:id" => fn(req) { ... }
164
+ POST "/users" => fn(req) { ... }
165
+ }
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Module: `std/json`
171
+
172
+ ```arc
173
+ use std/json: parse, stringify
174
+
175
+ let data = parse('{"name": "Arc", "version": 1}')
176
+ data.name # "Arc"
177
+
178
+ let text = stringify(data) # '{"name":"Arc","version":1}'
179
+ let pretty = stringify(data, indent: 2)
180
+
181
+ # Usually unnecessary — @ tool calls auto-parse JSON
182
+ let user = @GET "api/users/1" # Already parsed
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Module: `std/io`
188
+
189
+ ```arc
190
+ use std/io: readLines, appendFile, exists, mkdir, ls, rm, glob
191
+
192
+ # File operations (read/write are in prelude)
193
+ let lines = readLines("data.txt") # [String]
194
+ appendFile("log.txt", "entry\n")
195
+ let found = exists("config.json") # Bool
196
+
197
+ # Directory operations
198
+ mkdir("output")
199
+ let files = ls("src") # [String]
200
+ let arcs = glob("**/*.arc") # [String]
201
+
202
+ # Stdin
203
+ use std/io: input
204
+ let name = input("What's your name? ")
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Module: `std/async`
210
+
211
+ ```arc
212
+ use std/async: spawn, sleep, timeout, channel, select
213
+
214
+ # Spawn concurrent task
215
+ let task = spawn { heavyWork() }
216
+ let result = await task
217
+
218
+ # Sleep
219
+ sleep(1000) # ms
220
+
221
+ # Timeout
222
+ let data = timeout(5000) {
223
+ @GET "slow-api/data"
224
+ } ? defaultData
225
+
226
+ # Channels (CSP-style)
227
+ let (tx, rx) = channel()
228
+ spawn { tx.send("hello") }
229
+ let msg = rx.recv() # "hello"
230
+
231
+ # Select (wait for first)
232
+ match select [rx1, rx2, timeout(1000)] {
233
+ (0, msg) => handle1(msg)
234
+ (1, msg) => handle2(msg)
235
+ (2, _) => handleTimeout()
236
+ }
237
+ ```
238
+
239
+ **Rationale:** CSP-style channels (Go-inspired) are simpler than shared-memory concurrency. `select` provides multiplexing. `timeout` wraps any async operation with a deadline.
240
+
241
+ ---
242
+
243
+ ## Module: `std/csv`
244
+
245
+ ```arc
246
+ use std/csv: parseCSV, toCSV
247
+
248
+ let data = read "data.csv" |> parseCSV # [{name: "...", age: "..."}]
249
+ let text = data |> toCSV # Back to CSV string
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Module: `std/time`
255
+
256
+ ```arc
257
+ use std/time: now, format, parse, duration
258
+
259
+ let t = now() # Timestamp
260
+ let s = format(t, "YYYY-MM-DD") # "2026-02-16"
261
+ let d = duration(hours: 2, minutes: 30)
262
+ let later = t + d
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Module: `std/regex`
268
+
269
+ ```arc
270
+ use std/regex: regex, matchAll, replaceAll
271
+
272
+ let pat = regex("[0-9]+")
273
+ let found = "abc 123 def 456" |> matchAll(pat) # ["123", "456"]
274
+ let cleaned = "abc 123" |> replaceAll(pat, "#") # "abc #"
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Module: `std/crypto`
280
+
281
+ ```arc
282
+ use std/crypto: hash, hmac, encrypt, decrypt, uuid
283
+
284
+ let h = hash("sha256", "hello")
285
+ let id = uuid() # "550e8400-e29b-..."
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Module: `std/test`
291
+
292
+ ```arc
293
+ use std/test: test, assert, assertEq, assertErr
294
+
295
+ test "addition" {
296
+ assertEq(add(2, 3), 5)
297
+ }
298
+
299
+ test "division by zero" {
300
+ assertErr(divide(1, 0))
301
+ }
302
+
303
+ test "user validation" {
304
+ let user = User({name: "Arc", email: "arc@test.com", age: 1})
305
+ assert(user.age > 0)
306
+ }
307
+ ```
308
+
309
+ ---
310
+
311
+ ## API Design Patterns
312
+
313
+ ### 1. Functions over methods
314
+ ```arc
315
+ # Arc prefers free functions (work with |>)
316
+ len(items) # not items.length
317
+ sort(items) # not items.sort()
318
+ filter(items, fn) # not items.filter(fn)
319
+ ```
320
+
321
+ **Rationale:** Free functions compose with `|>`. No method resolution overhead. Agents don't need to remember which type has which method.
322
+
323
+ ### 2. Options as last parameter
324
+ ```arc
325
+ fn request(url, method = "GET", headers = {}, timeout = 30000)
326
+ ```
327
+
328
+ ### 3. Result types for fallible operations
329
+ ```arc
330
+ fn readFile(path) -> Result<String> # not throw
331
+ fn parse(text) -> Result<Value> # not throw
332
+ ```
333
+
334
+ ### 4. Overloading by arity
335
+ ```arc
336
+ rand() # 0.0..1.0
337
+ rand(max) # 0..max
338
+ rand(min, max) # min..max
339
+ ```
340
+
341
+ ---
342
+
343
+ ## Token Efficiency Summary
344
+
345
+ | Operation | JS stdlib | Python stdlib | Arc stdlib | vs JS | vs Python |
346
+ |-----------|-----------|---------------|------------|-------|-----------|
347
+ | Read file | `fs.readFileSync(p,'utf8')` | `open(p).read()` | `read p` | -70% | -50% |
348
+ | Parse JSON | `JSON.parse(text)` | `json.loads(text)` | `parse(text)` | -30% | -25% |
349
+ | HTTP GET | `await fetch(url).then(r=>r.json())` | `requests.get(url).json()` | `@GET url` | -75% | -60% |
350
+ | Sort by key | `arr.sort((a,b)=>a.k-b.k)` | `sorted(arr,key=lambda x:x.k)` | `sort(arr,x=>x.k)` | -40% | -30% |
351
+ | Filter | `arr.filter(x=>x.active)` | `[x for x in arr if x.active]` | `filter(arr,x=>x.active)` | -10% | -20% |
352
+ | **Average** | | | | **-45%** | **-37%** |
353
+
354
+ ---
355
+
356
+ **Last Updated:** 2026-02-16
357
+ **Status:** Draft v0.1