Skip to content

Commit ee0c03e

Browse files
committed
gemini refactor for rs taste; tag 0.9.16
1 parent f7fce19 commit ee0c03e

File tree

11 files changed

+159
-259
lines changed

11 files changed

+159
-259
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
[package]
33
name = "calcit"
4-
version = "0.9.15"
4+
version = "0.9.16"
55
authors = ["jiyinyiyong <jiyinyiyong@gmail.com>"]
66
edition = "2024"
77
license = "MIT"
@@ -53,6 +53,6 @@ path = "src/bin/bundle_calcit.rs"
5353
name = "caps"
5454
path = "src/bin/calcit_deps.rs"
5555

56-
# [profile.release]
57-
# debug = true
58-
# opt-level = 1
56+
[profile.release]
57+
lto = true
58+
opt-level = 3

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@calcit/procs",
3-
"version": "0.9.15",
3+
"version": "0.9.16",
44
"main": "./lib/calcit.procs.mjs",
55
"devDependencies": {
66
"@types/node": "^22.15.24",

src/builtins/lists.rs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use core::cmp::Ordering;
22
use std::sync::Arc;
33

4+
use rpds::HashTrieSet;
5+
46
use crate::calcit::{Calcit, CalcitErr, CalcitList, CalcitTuple};
57
use crate::util::number::f64_to_usize;
68

@@ -44,15 +46,12 @@ pub fn slice(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
4446
}
4547
match (&xs[0], &xs[1]) {
4648
(Calcit::List(ys), Calcit::Number(from)) => {
49+
let from_idx = f64_to_usize(*from)?;
4750
let to_idx = match xs.get(2) {
48-
Some(Calcit::Number(to)) => {
49-
let idx: usize = unsafe { to.to_int_unchecked() };
50-
idx
51-
}
51+
Some(Calcit::Number(to)) => f64_to_usize(*to)?,
5252
Some(a) => return CalcitErr::err_str(format!("slice expected number index, got: {a}")),
5353
None => ys.len(),
5454
};
55-
let from_idx: usize = unsafe { from.to_int_unchecked() };
5655

5756
Ok(Calcit::List(Arc::new(ys.slice(from_idx, to_idx)?)))
5857
}
@@ -112,16 +111,23 @@ pub fn butlast(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
112111
}
113112

114113
pub fn concat(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
115-
let mut ys = vec![];
114+
let mut total_size = 0;
116115
for x in xs {
117116
if let Calcit::List(zs) = x {
118-
for z in &**zs {
119-
ys.push(z.to_owned());
120-
}
117+
total_size += zs.len();
121118
} else {
122119
return CalcitErr::err_str(format!("concat expects list arguments, got: {x}"));
123120
}
124121
}
122+
123+
let mut ys = Vec::with_capacity(total_size);
124+
for x in xs {
125+
if let Calcit::List(zs) = x {
126+
// Use extend to efficiently append elements from the inner list
127+
ys.extend(zs.iter().map(|v| v.to_owned()));
128+
}
129+
// no need for else, already checked
130+
}
125131
Ok(Calcit::List(Arc::new(CalcitList::Vector(ys))))
126132
}
127133

@@ -184,13 +190,13 @@ pub fn foldl(xs: &[Calcit], call_stack: &CallStackList) -> Result<Calcit, Calcit
184190
match (&xs[0], &xs[2]) {
185191
// dirty since only functions being call directly then we become fast
186192
(Calcit::List(xs), Calcit::Fn { info, .. }) => {
187-
for x in &**xs {
193+
for x in xs.iter() {
188194
ret = runner::run_fn(&[ret, (*x).to_owned()], info, call_stack)?;
189195
}
190196
Ok(ret)
191197
}
192198
(Calcit::List(xs), Calcit::Proc(proc)) => {
193-
for x in &**xs {
199+
for x in xs.iter() {
194200
// println!("foldl args, {} {}", ret, x.to_owned());
195201
ret = builtins::handle_proc(*proc, &[ret, (*x).to_owned()], call_stack)?;
196202
}
@@ -257,7 +263,7 @@ pub fn foldl_shortcut(xs: &[Calcit], call_stack: &CallStackList) -> Result<Calci
257263
// dirty since only functions being call directly then we become fast
258264
(Calcit::List(xs), Calcit::Fn { info, .. }) => {
259265
let mut state = acc.to_owned();
260-
for x in &**xs {
266+
for x in xs.iter() {
261267
let pair = runner::run_fn(&[state.to_owned(), (*x).to_owned()], info, call_stack)?;
262268
match pair {
263269
Calcit::Tuple(CalcitTuple { tag: x0, extra, .. }) => match &*x0 {
@@ -456,10 +462,7 @@ pub fn sort(xs: &[Calcit], call_stack: &CallStackList) -> Result<Calcit, CalcitE
456462
match (&xs[0], &xs[1]) {
457463
// dirty since only functions being call directly then we become fast
458464
(Calcit::List(xs), Calcit::Fn { info, .. }) => {
459-
let mut xs2: Vec<Calcit> = vec![];
460-
xs.traverse(&mut |x| {
461-
xs2.push(x.to_owned());
462-
});
465+
let mut xs2: Vec<Calcit> = xs.to_vec(); // Use existing to_vec()
463466
xs2.sort_by(|a, b| -> Ordering {
464467
let v = runner::run_fn(&[(*a).to_owned(), (*b).to_owned()], info, call_stack);
465468
match v {
@@ -476,17 +479,10 @@ pub fn sort(xs: &[Calcit], call_stack: &CallStackList) -> Result<Calcit, CalcitE
476479
}
477480
}
478481
});
479-
let mut ys = CalcitList::new_inner();
480-
for x in xs2.iter() {
481-
ys = ys.push_right(x.to_owned())
482-
}
483-
Ok(Calcit::List(Arc::new(ys.into())))
482+
Ok(Calcit::List(Arc::new(CalcitList::Vector(xs2))))
484483
}
485484
(Calcit::List(xs), Calcit::Proc(proc)) => {
486-
let mut xs2: Vec<Calcit> = vec![];
487-
xs.traverse(&mut |x| {
488-
xs2.push(x.to_owned());
489-
});
485+
let mut xs2: Vec<Calcit> = xs.to_vec(); // Use existing to_vec()
490486
xs2.sort_by(|a, b| -> Ordering {
491487
let v = builtins::handle_proc(*proc, &[(*a).to_owned(), (*b).to_owned()], call_stack);
492488
match v {
@@ -503,11 +499,7 @@ pub fn sort(xs: &[Calcit], call_stack: &CallStackList) -> Result<Calcit, CalcitE
503499
}
504500
}
505501
});
506-
let mut ys = CalcitList::new_inner();
507-
for x in xs2.iter() {
508-
ys = ys.push_right(x.to_owned())
509-
}
510-
Ok(Calcit::List(Arc::new(ys.into())))
502+
Ok(Calcit::List(Arc::new(CalcitList::Vector(xs2)))) // Directly create from Vec
511503
}
512504
(a, b) => Err(CalcitErr::use_msg_stack_location(
513505
format!("sort expected list and function, got: {a} {b}"),
@@ -661,9 +653,11 @@ pub fn distinct(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
661653
}
662654
match &xs[0] {
663655
Calcit::List(ys) => {
656+
let mut seen = HashTrieSet::new_sync();
664657
let mut zs = CalcitList::new_inner();
665658
ys.traverse(&mut |y| {
666-
if zs.index_of(y).is_none() {
659+
if !seen.contains(y) {
660+
seen.insert_mut(y.to_owned());
667661
zs = zs.push_right(y.to_owned());
668662
}
669663
});

src/builtins/strings.rs

Lines changed: 52 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
use std::char;
21
use std::cmp::Ordering;
32

4-
use im_ternary_tree::TernaryTreeList;
5-
6-
use crate::calcit::CalcitList;
7-
use crate::calcit::{Calcit, CalcitErr};
3+
use crate::calcit::{Calcit, CalcitErr, CalcitList};
84
use crate::util::number::f64_to_usize;
95

106
pub fn binary_str_concat(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
117
match (xs.first(), xs.get(1)) {
128
(Some(Calcit::Nil), Some(Calcit::Nil)) => Ok(Calcit::new_str("")),
139
(Some(Calcit::Nil), Some(b)) => Ok(Calcit::Str(b.turn_string().into())),
1410
(Some(a), Some(Calcit::Nil)) => Ok(Calcit::Str(a.turn_string().into())),
11+
(Some(Calcit::Str(s1)), Some(Calcit::Str(s2))) => {
12+
let mut s = String::with_capacity(s1.len() + s2.len());
13+
s.push_str(s1);
14+
s.push_str(s2);
15+
Ok(Calcit::Str(s.into()))
16+
}
1517
(Some(a), Some(b)) => {
1618
let mut s = a.turn_string();
1719
s.push_str(&b.turn_string());
@@ -61,14 +63,12 @@ pub fn turn_string(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
6163
pub fn split(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
6264
match (xs.first(), xs.get(1)) {
6365
(Some(Calcit::Str(s)), Some(Calcit::Str(pattern))) => {
64-
let pieces = (**s).split(&**pattern);
65-
let mut ys = vec![];
66-
for p in pieces {
67-
if !p.is_empty() {
68-
ys.push(Calcit::Str(p.into()));
69-
}
70-
}
71-
Ok(Calcit::from(ys))
66+
let pieces = (**s)
67+
.split(&**pattern)
68+
.filter(|s| !s.is_empty())
69+
.map(|s| Calcit::Str(s.into()))
70+
.collect::<Vec<Calcit>>();
71+
Ok(Calcit::from(pieces))
7272
}
7373
(Some(a), Some(b)) => CalcitErr::err_str(format!("split expected 2 strings, got: {a} {b}")),
7474
(_, _) => CalcitErr::err_str("split expected 2 arguments, got nothing"),
@@ -114,41 +114,32 @@ pub fn replace(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
114114
pub fn split_lines(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
115115
match xs.first() {
116116
Some(Calcit::Str(s)) => {
117-
let lines = s.split('\n');
118-
let mut ys = TernaryTreeList::Empty;
119-
for line in lines {
120-
ys = ys.push_right(Calcit::Str(line.to_owned().into()));
121-
}
122-
Ok(Calcit::from(CalcitList::List(ys)))
117+
let lines = s.lines().map(|line| Calcit::Str(line.to_owned().into())).collect::<Vec<Calcit>>();
118+
Ok(Calcit::from(lines))
123119
}
124120
Some(a) => CalcitErr::err_str(format!("split-lines expected 1 string, got: {a}")),
125121
_ => CalcitErr::err_str("split-lines expected 1 argument, got nothing"),
126122
}
127123
}
128124
pub fn str_slice(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
129-
match (xs.first(), xs.get(1)) {
130-
(Some(Calcit::Str(s)), Some(Calcit::Number(n))) => match f64_to_usize(*n) {
131-
Ok(from) => {
132-
let to: usize = match xs.get(2) {
133-
Some(Calcit::Number(n2)) => match f64_to_usize(*n2) {
134-
Ok(idx2) => idx2,
135-
Err(e) => return CalcitErr::err_str(format!("&str:slice expected number, got: {e}")),
136-
},
137-
Some(a) => return CalcitErr::err_str(format!("&str:slice expected number, got: {a}")),
138-
None => s.chars().count(),
139-
};
140-
if from >= to {
141-
Ok(Calcit::new_str(""))
142-
} else {
143-
// turn into vec first to also handle UTF8
144-
let s_vec = s.chars().collect::<Vec<_>>();
145-
Ok(Calcit::Str(s_vec[from..to].iter().to_owned().collect::<String>().into()))
146-
}
125+
match (xs.first(), xs.get(1), xs.get(2)) {
126+
(Some(Calcit::Str(s)), Some(Calcit::Number(n_from)), n_to) => {
127+
let from = f64_to_usize(*n_from)?;
128+
let to = match n_to {
129+
Some(Calcit::Number(n)) => f64_to_usize(*n)?,
130+
Some(a) => return CalcitErr::err_str(format!("&str:slice expected number, got: {a}")),
131+
None => s.chars().count(),
132+
};
133+
134+
if from >= to {
135+
Ok(Calcit::new_str(""))
136+
} else {
137+
let s: String = s.chars().skip(from).take(to - from).collect();
138+
Ok(Calcit::Str(s.into()))
147139
}
148-
Err(e) => CalcitErr::err_str(e),
149-
},
150-
(Some(a), Some(b)) => CalcitErr::err_str(format!("&str:slice expected string and number, got: {a} {b}")),
151-
(_, _) => CalcitErr::err_nodes("&str:slice expected string and numbers, got:", xs),
140+
}
141+
(Some(a), Some(b), ..) => CalcitErr::err_str(format!("&str:slice expected string and number, got: {a} {b}")),
142+
(_, _, _) => CalcitErr::err_nodes("&str:slice expected string and numbers, got:", xs),
152143
}
153144
}
154145

@@ -321,18 +312,7 @@ pub fn first(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
321312

322313
pub fn rest(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
323314
match xs.first() {
324-
Some(Calcit::Str(s)) => {
325-
let mut buffer = String::with_capacity(s.len() - 1);
326-
let mut is_first = true;
327-
for c in s.chars() {
328-
if is_first {
329-
is_first = false;
330-
continue;
331-
}
332-
buffer.push(c)
333-
}
334-
Ok(Calcit::Str(buffer.into()))
335-
}
315+
Some(Calcit::Str(s)) => Ok(Calcit::Str(s.chars().skip(1).collect::<String>().into())),
336316
Some(a) => CalcitErr::err_str(format!("str:rest expected a string, got: {a}")),
337317
None => CalcitErr::err_str("str:rest expected 1 argument, got nothing"),
338318
}
@@ -347,21 +327,17 @@ pub fn pad_left(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
347327
return CalcitErr::err_str("&str:pad-left expected non-empty pattern");
348328
}
349329
if s.len() >= size {
350-
Ok(xs[0].to_owned())
351-
} else {
352-
let mut buffer = String::with_capacity(size);
353-
let pad_size = size - s.len();
354-
'write: loop {
355-
for c in pattern.chars() {
356-
buffer.push(c);
357-
if buffer.len() >= pad_size {
358-
break 'write;
359-
}
360-
}
361-
}
362-
buffer.push_str(s);
363-
Ok(Calcit::Str(buffer.into()))
330+
return Ok(xs[0].to_owned());
331+
}
332+
333+
let pad_size = size - s.len();
334+
let mut buffer = String::with_capacity(size);
335+
// Directly iterate over pattern characters
336+
for c in pattern.chars().cycle().take(pad_size) {
337+
buffer.push(c);
364338
}
339+
buffer.push_str(s);
340+
Ok(Calcit::Str(buffer.into()))
365341
}
366342
(a, b, c) => CalcitErr::err_str(format!("&str:pad-left expected string, number, string, got: {a} {b} {c}")),
367343
}
@@ -379,20 +355,16 @@ pub fn pad_right(xs: &[Calcit]) -> Result<Calcit, CalcitErr> {
379355
return CalcitErr::err_str("&str:pad-right expected non-empty pattern");
380356
}
381357
if s.len() >= size {
382-
Ok(xs[0].to_owned())
383-
} else {
384-
let mut buffer = String::with_capacity(size);
385-
buffer.push_str(s);
386-
'write: loop {
387-
for c in pattern.chars() {
388-
buffer.push(c);
389-
if buffer.len() >= size {
390-
break 'write;
391-
}
392-
}
393-
}
394-
Ok(Calcit::Str(buffer.into()))
358+
return Ok(xs[0].to_owned());
359+
}
360+
361+
let mut buffer = String::with_capacity(size);
362+
buffer.push_str(s);
363+
// Directly iterate over pattern characters
364+
for c in pattern.chars().cycle().take(size - s.len()) {
365+
buffer.push(c);
395366
}
367+
Ok(Calcit::Str(buffer.into()))
396368
}
397369
(a, b, c) => CalcitErr::err_str(format!("&str:pad-right expected string, number, string, got: {a} {b} {c}")),
398370
}

src/calcit/list.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -352,14 +352,11 @@ impl CalcitList {
352352
}
353353

354354
pub fn assoc_after(&self, idx: usize, x: Calcit) -> Result<Self, String> {
355-
match self {
356-
CalcitList::Vector(xs) => {
357-
let mut ys = TernaryTreeList::from(xs);
358-
ys = ys.assoc_after(idx, x)?;
359-
Ok(CalcitList::List(ys))
360-
}
361-
CalcitList::List(xs) => Ok(CalcitList::List(xs.assoc_after(idx, x)?)),
362-
}
355+
let base_list = match self {
356+
CalcitList::Vector(xs) => TernaryTreeList::from(xs),
357+
CalcitList::List(xs) => xs.clone(),
358+
};
359+
Ok(CalcitList::List(base_list.assoc_after(idx, x)?))
363360
}
364361

365362
pub fn index_of(&self, x: &Calcit) -> Option<usize> {

src/data.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ pub fn data_to_calcit(x: &Calcit, ns: &str, at_def: &str) -> Result<Calcit, Stri
4242
Ok(Calcit::from(ys))
4343
}
4444
Calcit::List(xs) => {
45-
let mut ys = vec![Calcit::Proc(CalcitProc::List)];
45+
let mut ys = Vec::with_capacity(xs.len() + 1);
46+
ys.push(Calcit::Proc(CalcitProc::List));
4647
xs.traverse_result::<String>(&mut |x| {
4748
ys.push(data_to_calcit(x, ns, at_def)?);
4849
Ok(())

0 commit comments

Comments
 (0)