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.
- package/README.md +65 -130
- package/dist/ast.d.ts +30 -2
- package/dist/build.js +1 -1
- package/dist/formatter.js +15 -3
- package/dist/index.js +104 -0
- package/dist/interpreter.js +130 -17
- package/dist/lexer.d.ts +41 -37
- package/dist/lexer.js +47 -39
- package/dist/linter.js +18 -0
- package/dist/modules.js +5 -1
- package/dist/parser.d.ts +2 -0
- package/dist/parser.js +91 -11
- package/dist/repl.js +66 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -2
- package/stdlib/API_DESIGN.md +357 -0
- package/stdlib/ASYNC_DESIGN.md +815 -0
- package/stdlib/EXAMPLES.md +710 -0
- package/stdlib/MODULES.md +854 -0
- package/stdlib/README.md +64 -0
- package/stdlib/collections.arc +140 -0
- package/stdlib/crypto.arc +62 -0
- package/stdlib/csv.arc +40 -0
- package/stdlib/datetime.arc +75 -0
- package/stdlib/embed.arc +42 -0
- package/stdlib/env.arc +10 -0
- package/stdlib/error.arc +36 -0
- package/stdlib/html.arc +30 -0
- package/stdlib/http.arc +43 -0
- package/stdlib/io.arc +28 -0
- package/stdlib/json.arc +204 -0
- package/stdlib/llm.arc +193 -0
- package/stdlib/log.arc +20 -0
- package/stdlib/map.arc +72 -0
- package/stdlib/math.arc +133 -0
- package/stdlib/net.arc +17 -0
- package/stdlib/os.arc +81 -0
- package/stdlib/path.arc +11 -0
- package/stdlib/prompt.arc +49 -0
- package/stdlib/regex.arc +59 -0
- package/stdlib/result.arc +50 -0
- package/stdlib/store.arc +62 -0
- package/stdlib/strings.arc +44 -0
- package/stdlib/test.arc +61 -0
- package/stdlib/time.arc +19 -0
- package/stdlib/toml.arc +10 -0
- 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.
|
|
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
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arc-lang",
|
|
3
|
-
"version": "0.6.
|
|
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
|
-
"
|
|
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
|