Skip to content

Commit e7df2e1

Browse files
authored
feat: expand stdlib common modules (#6)
* feat: optimize method map get lowering * feat: expand stdlib common modules * fix: address stdlib review findings
1 parent 63b12a2 commit e7df2e1

50 files changed

Lines changed: 2912 additions & 921 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 447 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,26 @@ members = [
77
"stdlib/crates/bytes",
88
"stdlib/crates/chan",
99
"stdlib/crates/datetime",
10+
"stdlib/crates/encoding",
11+
"stdlib/crates/env",
12+
"stdlib/crates/fs",
13+
"stdlib/crates/hash",
14+
"stdlib/crates/http",
1015
"stdlib/crates/io",
1116
"stdlib/crates/iter",
12-
"stdlib/crates/json",
1317
"stdlib/crates/math",
1418
"stdlib/crates/net",
1519
"stdlib/crates/os",
20+
"stdlib/crates/path",
21+
"stdlib/crates/process",
22+
"stdlib/crates/random",
23+
"stdlib/crates/regex",
1624
"stdlib/crates/slice",
1725
"stdlib/crates/stream",
1826
"stdlib/crates/string",
1927
"stdlib/crates/task",
2028
"stdlib/crates/time",
21-
"stdlib/crates/toml",
22-
"stdlib/crates/yaml",
29+
"stdlib/crates/uuid",
2330
"lkrt",
2431
"lsp",
2532
"tree-sitter-lk",
@@ -40,9 +47,16 @@ serde = { version = "1", features = ["derive", "rc"] }
4047
serde_json = "1"
4148
serde_yaml = "0"
4249
toml = "1"
50+
base64 = "0.22"
51+
crc32fast = "1"
52+
hex = "0.4"
4353
once_cell = "1"
4454
chrono = "0"
4555
sanitize-filename = "0"
56+
rand = "0.9"
57+
regex = "1"
58+
sha1 = "0.10"
59+
sha2 = "0.10"
4660
tokio = { version = "1", features = [
4761
"rt-multi-thread",
4862
"macros",
@@ -57,6 +71,9 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
5771
tempfile = "3"
5872
llvm-tools = "0.1"
5973
arcstr = { version = "1", features = ["serde"] }
74+
ureq = "2"
75+
url = "2"
76+
uuid = { version = "1", features = ["v4"] }
6077

6178
[profile.release]
6279
panic = "abort"

bench/workloads_business_algorithms.lk

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Each block measures runtime only and prints: workload|name|checksum=...|elapsed=...ms
33
use os;
44
use math;
5-
use map;
6-
use string;
75

86
let seed = os.epoch();
97
let workload_filter = os.env.get("LK_WORKLOAD_FILTER", "");
@@ -112,7 +110,7 @@ if should_run("two_sum_map") {
112110
for i in 1..=two_sum_width {
113111
let need = target - i;
114112
let need_key = "n${need}";
115-
if map.get(seen, need_key) != nil {
113+
if seen.get(need_key) != nil {
116114
found += 1;
117115
}
118116
}
@@ -201,7 +199,7 @@ if should_run("histogram_group_count") {
201199
for i in 1..=hist_n {
202200
let bucket = ((i * 17) + r) % 32;
203201
let key = "b${bucket}";
204-
let prev = map.get(hist, key);
202+
let prev = hist.get(key);
205203
if prev == nil {
206204
hist.set(key, 1);
207205
} else {
@@ -210,7 +208,7 @@ if should_run("histogram_group_count") {
210208
}
211209
for b in 0..32 {
212210
let key = "b${b}";
213-
let v = map.get(hist, key);
211+
let v = hist.get(key);
214212
if v != nil {
215213
checksum += v * v;
216214
}
@@ -266,7 +264,7 @@ if should_run("log_parse_filter") {
266264
let line = "ts=${r}|tenant=t${i % 13}|status=error|path=/api/v1/orders/${i % 19}";
267265
let parsed_len = line.split("|").join("|").len();
268266
checksum += parsed_len % 7;
269-
let prev = map.get(status_counts, "error");
267+
let prev = status_counts.get("error");
270268
if prev == nil {
271269
status_counts.set("error", 1);
272270
} else {
@@ -276,7 +274,7 @@ if should_run("log_parse_filter") {
276274
let line = "ts=${r}|tenant=t${i % 13}|status=warn|path=/api/v1/orders/${i % 19}";
277275
let parsed_len = line.split("|").join("|").len();
278276
checksum += parsed_len % 7;
279-
let prev = map.get(status_counts, "warn");
277+
let prev = status_counts.get("warn");
280278
if prev == nil {
281279
status_counts.set("warn", 1);
282280
} else {
@@ -286,17 +284,17 @@ if should_run("log_parse_filter") {
286284
let line = "ts=${r}|tenant=t${i % 13}|status=${status}|path=/api/v1/orders/${i % 19}";
287285
let parsed_len = line.split("|").join("|").len();
288286
checksum += parsed_len % 7;
289-
let prev = map.get(status_counts, status);
287+
let prev = status_counts.get(status);
290288
if prev == nil {
291289
status_counts.set(status, 1);
292290
} else {
293291
status_counts.set(status, prev + 1);
294292
}
295293
}
296294
}
297-
let ok_count = map.get(status_counts, "ok");
298-
let warn_count = map.get(status_counts, "warn");
299-
let error_count = map.get(status_counts, "error");
295+
let ok_count = status_counts.get("ok");
296+
let warn_count = status_counts.get("warn");
297+
let error_count = status_counts.get("error");
300298
if ok_count != nil { checksum += ok_count; }
301299
if warn_count != nil { checksum += warn_count * 7; }
302300
if error_count != nil { checksum += error_count * 31; }
@@ -306,8 +304,8 @@ if should_run("log_parse_filter") {
306304
}
307305

308306
fn cart_line_total(sku, qty, region, prices, tax_rates) {
309-
let price = map.get(prices, sku);
310-
let tax = map.get(tax_rates, region);
307+
let price = prices.get(sku);
308+
let tax = tax_rates.get(region);
311309
let subtotal = price * qty;
312310
let discount = 0;
313311
if qty >= 5 {
@@ -349,15 +347,15 @@ if should_run("route_permission_check") {
349347
let role_levels = {"guest": 0, "user": 10, "analyst": 40, "ops": 70, "admin": 100};
350348
for i in 1..=route_rounds {
351349
if ((i % 11) == 0) {
352-
checksum += (i % 97) + map.get(role_levels, "admin") + "/admin/users".len();
350+
checksum += (i % 97) + role_levels.get("admin") + "/admin/users".len();
353351
} else if ((i % 7) == 0) {
354-
checksum += (i % 97) + map.get(role_levels, "ops") + "DELETE".len();
352+
checksum += (i % 97) + role_levels.get("ops") + "DELETE".len();
355353
} else if ((i % 5) == 0) {
356-
checksum += (i % 97) + map.get(role_levels, "analyst") + "/reports/daily".len();
354+
checksum += (i % 97) + role_levels.get("analyst") + "/reports/daily".len();
357355
} else if ((i % 2) == 0) {
358-
checksum += (i % 97) + map.get(role_levels, "user") + "/api/orders".len();
356+
checksum += (i % 97) + role_levels.get("user") + "/api/orders".len();
359357
} else {
360-
checksum += 3 + map.get(role_levels, "guest");
358+
checksum += 3 + role_levels.get("guest");
361359
}
362360
}
363361
t1 = os.clock();
@@ -373,7 +371,7 @@ if should_run("inventory_reorder") {
373371
let reorder = [];
374372
for i in 1..=64 {
375373
let sku = "sku-${i % 23}";
376-
let current = map.get(stock, sku);
374+
let current = stock.get(sku);
377375
let delta = ((i * 11) + r) % 37;
378376
if current == nil {
379377
stock.set(sku, delta);
@@ -383,7 +381,7 @@ if should_run("inventory_reorder") {
383381
}
384382
for i in 0..23 {
385383
let sku = "sku-${i}";
386-
let available = map.get(stock, sku);
384+
let available = stock.get(sku);
387385
if available == nil {
388386
available = 0;
389387
}
@@ -408,7 +406,7 @@ fn fraud_score(amount, country, device, prior_declines, risky_countries) {
408406
} else if amount > 400 {
409407
score += 15;
410408
}
411-
if map.get(risky_countries, country) != nil {
409+
if risky_countries.get(country) != nil {
412410
score += 35;
413411
}
414412
if device.starts_with("emu") {
@@ -511,9 +509,9 @@ if should_run("event_join_by_id") {
511509
}
512510
for e in 0..event_n {
513511
let uid = "u${(e * 7 + r) % user_n}";
514-
let quota = map.get(user_quotas, uid);
512+
let quota = user_quotas.get(uid);
515513
if quota != nil {
516-
let plan = map.get(user_plans, uid);
514+
let plan = user_plans.get(uid);
517515
checksum += quota % 31;
518516
if plan == 3 {
519517
checksum += 41;
@@ -539,13 +537,13 @@ if should_run("config_defaults_merge") {
539537
if ((i % 3) == 0) { config.set("timeout", 30 + (i % 17)); }
540538
if ((i % 5) == 0) { config.set("region", 2); }
541539
if ((i % 7) == 0) { config.set("mode", 2); }
542-
let retries = map.get(config, "retries");
540+
let retries = config.get("retries");
543541
if retries == nil { retries = 3; }
544-
let timeout = map.get(config, "timeout");
542+
let timeout = config.get("timeout");
545543
if timeout == nil { timeout = 25; }
546-
let region = map.get(config, "region");
544+
let region = config.get("region");
547545
if region == nil { region = 1; }
548-
let mode = map.get(config, "mode");
546+
let mode = config.get("mode");
549547
if mode == nil { mode = 1; }
550548
checksum += retries * 13 + timeout;
551549
if region == 2 { checksum += 17; } else { checksum += 5; }

core/src/vm/compiler/call.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ impl Compiler {
5858
let callee = self.lower_readonly_operand(callee)?;
5959
return self.lower_call_window_boxes(callee, args);
6060
}
61+
if let Some((target, key)) = map_get_method_call_args(callee, args) {
62+
return self.lower_map_get_method_call(target, key);
63+
}
6164
return self.lower_builtin_method_call(target, method, args);
6265
}
6366
let callee = self.lower_readonly_operand(callee)?;
@@ -90,18 +93,32 @@ impl Compiler {
9093
Ok(dst)
9194
}
9295

96+
fn lower_map_get_method_call(&mut self, target: &Expr, key: &Expr) -> Result<u16> {
97+
let dst = self.alloc_reg();
98+
self.lower_map_get_expr_to_register(dst, target, key)?;
99+
Ok(dst)
100+
}
101+
93102
pub(super) fn lower_map_get_function_call_to_register(&mut self, dst: u16, args: &[Box<Expr>]) -> Result<()> {
94103
if args.len() != 2 {
95104
bail!("Compiler map.get expects 2 args, got {}", args.len());
96105
}
97-
if let Some(value) = self.lower_const_map_get(&args[0], &args[1])? {
106+
self.lower_map_get_expr_to_register(dst, &args[0], &args[1])
107+
}
108+
109+
pub(super) fn lower_map_get_method_call_to_register(&mut self, dst: u16, target: &Expr, key: &Expr) -> Result<()> {
110+
self.lower_map_get_expr_to_register(dst, target, key)
111+
}
112+
113+
fn lower_map_get_expr_to_register(&mut self, dst: u16, target_expr: &Expr, key_expr: &Expr) -> Result<()> {
114+
if let Some(value) = self.lower_const_map_get(target_expr, key_expr)? {
98115
let move_source = !self.is_current_local_slot(value);
99116
self.emit_move_with_policy(dst, value, "map.get const value", move_source)?;
100117
return Ok(());
101118
}
102-
let target = self.lower_readonly_index_operand(&args[0])?;
119+
let target = self.lower_readonly_index_operand(target_expr)?;
103120
let index_fact = index_fact_from_target(&self.function.performance, target);
104-
if let Some((suffix, key_fact)) = self.try_lower_string_int_key_for_map(index_fact, &args[1])? {
121+
if let Some((suffix, key_fact)) = self.try_lower_string_int_key_for_map(index_fact, key_expr)? {
105122
let pc = self.function.code.len();
106123
self.emit(Instr::abc(
107124
Opcode::GetIndexStrI,
@@ -116,7 +133,7 @@ impl Compiler {
116133
}
117134
return Ok(());
118135
}
119-
let (key, key_fact) = self.lower_readonly_index_key_for_target(target, index_fact, &args[1])?;
136+
let (key, key_fact) = self.lower_readonly_index_key_for_target(target, index_fact, key_expr)?;
120137
let pc = self.function.code.len();
121138
if let Some(const_key) = get_field_key(index_fact, key_fact) {
122139
self.emit(Instr::abc(
@@ -992,6 +1009,19 @@ fn method_name(expr: &Expr) -> Option<&str> {
9921009
}
9931010
}
9941011

1012+
pub(super) fn map_get_method_call_args<'a>(callee: &'a Expr, args: &'a [Box<Expr>]) -> Option<(&'a Expr, &'a Expr)> {
1013+
if args.len() != 1 {
1014+
return None;
1015+
}
1016+
let Expr::Access(target, method) = callee else {
1017+
return None;
1018+
};
1019+
if method_name(method) != Some("get") {
1020+
return None;
1021+
}
1022+
Some((target.as_ref(), args[0].as_ref()))
1023+
}
1024+
9951025
fn literal_string_text(expr: &Expr) -> Option<&str> {
9961026
match expr {
9971027
Expr::Paren(inner) => literal_string_text(inner),

core/src/vm/compiler/loop_consts.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use crate::{
1111
};
1212

1313
use super::{
14-
Compiler, checked_u8,
14+
Compiler,
15+
call::map_get_method_call_args,
16+
checked_u8,
1517
inline::{inline_body_is_supported, stmt_contains_call_to},
1618
support::{FunctionInlineBody, const_runtime_map_key_from_literal},
1719
};
@@ -934,30 +936,40 @@ fn const_map_get_scalar_loop_key(
934936
expr: &Expr,
935937
const_maps: &HashMap<String, FastHashMap<RuntimeMapKey, ConstRuntimeValue>>,
936938
) -> Result<Option<ScalarLoopConstKey>> {
937-
let Expr::CallExpr(callee, args) = expr else {
939+
let Some((target, key)) = const_map_get_target_and_key(expr) else {
938940
return Ok(None);
939941
};
940-
if args.len() != 2 {
941-
return Ok(None);
942-
}
943-
let Expr::Access(target, method) = callee.as_ref() else {
944-
return Ok(None);
945-
};
946-
if !matches!(target.as_ref(), Expr::Var(name) if name == "map") || method_name(method) != Some("get") {
947-
return Ok(None);
948-
}
949-
let Some(target_name) = super::support::simple_local_expr_name(&args[0]) else {
942+
let Some(target_name) = super::support::simple_local_expr_name(target) else {
950943
return Ok(None);
951944
};
952945
let Some(map) = const_maps.get(target_name) else {
953946
return Ok(None);
954947
};
955-
let Some(key) = const_map_key_from_expr(&args[1])? else {
948+
let Some(key) = const_map_key_from_expr(key)? else {
956949
return Ok(None);
957950
};
958951
Ok(map.get(&key).and_then(const_runtime_scalar_loop_key))
959952
}
960953

954+
fn const_map_get_target_and_key(expr: &Expr) -> Option<(&Expr, &Expr)> {
955+
let Expr::CallExpr(callee, args) = expr else {
956+
return None;
957+
};
958+
if let Some((target, key)) = map_get_method_call_args(callee, args) {
959+
return Some((target, key));
960+
}
961+
if args.len() != 2 {
962+
return None;
963+
}
964+
let Expr::Access(target, method) = callee.as_ref() else {
965+
return None;
966+
};
967+
if !matches!(target.as_ref(), Expr::Var(name) if name == "map") || method_name(method) != Some("get") {
968+
return None;
969+
}
970+
Some((args[0].as_ref(), args[1].as_ref()))
971+
}
972+
961973
fn const_map_key_from_expr(expr: &Expr) -> Result<Option<RuntimeMapKey>> {
962974
match expr {
963975
Expr::Paren(inner) => const_map_key_from_expr(inner),

0 commit comments

Comments
 (0)