diff --git a/Cargo.lock b/Cargo.lock index 1f62f806..0b8fd6cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,7 +36,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "calcit" -version = "0.7.0" +version = "0.7.2" dependencies = [ "cirru_edn", "cirru_parser", diff --git a/Cargo.toml b/Cargo.toml index 02b81658..406adb9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "calcit" -version = "0.7.0" +version = "0.7.2" authors = ["jiyinyiyong "] edition = "2021" license = "MIT" diff --git a/calcit/test.cirru b/calcit/test.cirru index 55657f83..d5a0c36f 100644 --- a/calcit/test.cirru +++ b/calcit/test.cirru @@ -296,6 +296,13 @@ :: :t 1 :: :t 1 2 + let + a $ :: :a 1 + %r $ defrecord! %demo + :get $ fn (self) 1 + b $ &tuple:with-class a %r + assert= %r $ &tuple:class b + |test-effect $ quote fn () log-title "|Testing effect" diff --git a/package.json b/package.json index 9abb82ea..57dc35f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@calcit/procs", - "version": "0.7.0", + "version": "0.7.2", "main": "./lib/calcit.procs.mjs", "devDependencies": { "@types/node": "^20.2.5", diff --git a/src/builtins.rs b/src/builtins.rs index fb46eb2b..5b5f405a 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -78,6 +78,7 @@ fn handle_proc_internal(name: CalcitProc, args: &CalcitItems, call_stack: &CallS CalcitProc::NativeTupleAssoc => meta::assoc(args), CalcitProc::NativeTupleCount => meta::tuple_count(args), CalcitProc::NativeTupleClass => meta::tuple_class(args), + CalcitProc::NativeTupleWithClass => meta::tuple_with_class(args), // effects CalcitProc::NativeDisplayStack => meta::display_stack(args, call_stack), CalcitProc::Raise => effects::raise(args), diff --git a/src/builtins/meta.rs b/src/builtins/meta.rs index 7f71c312..3907e768 100644 --- a/src/builtins/meta.rs +++ b/src/builtins/meta.rs @@ -466,6 +466,20 @@ pub fn tuple_class(xs: &CalcitItems) -> Result { } } +pub fn tuple_with_class(xs: &CalcitItems) -> Result { + if xs.len() != 2 { + return CalcitErr::err_str(format!("tuple:with-class expected 2 arguments, got: {xs:?}")); + } + match (&xs[0], &xs[1]) { + (Calcit::Tuple(tag, extra, _), b @ Calcit::Record(..)) => { + Ok(Calcit::Tuple(tag.to_owned(), extra.to_owned(), Arc::new(b.to_owned()))) + } + (a, Calcit::Record(..)) => CalcitErr::err_str(format!("&tuple:with-class expected a tuple, got: {a}")), + (Calcit::Tuple(..), b) => CalcitErr::err_str(format!("&tuple:with-class expected second argument in record, got: {b}")), + (a, b) => CalcitErr::err_str(format!("&tuple:with-class expected a tuple and a record, got: {a} {b}")), + } +} + pub fn no_op() -> Result { Ok(Calcit::Nil) } diff --git a/src/cirru/calcit-core.cirru b/src/cirru/calcit-core.cirru index 529d192a..ff8df5c5 100644 --- a/src/cirru/calcit-core.cirru +++ b/src/cirru/calcit-core.cirru @@ -1817,3 +1817,10 @@ if (some? y) range (inc (&- (&+ x x) y)) y range (inc (negate x)) x + + |: $ quote + defmacro : (tag & args) + quasiquote + :: + ~ $ turn-tag tag + ~@ args diff --git a/src/data/cirru.rs b/src/data/cirru.rs index 1147925d..aa14ee8f 100644 --- a/src/data/cirru.rs +++ b/src/data/cirru.rs @@ -27,7 +27,7 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc, coord: &[u8]) -> location: Some(coord.to_vec()), }), _ => match s.chars().next().expect("load first char") { - ':' => Ok(Calcit::tag(&s[1..])), + ':' if s.len() > 1 && s.chars().nth(1) != Some(':') => Ok(Calcit::tag(&s[1..])), '.' => { if let Some(stripped) = s.strip_prefix(".-") { Ok(Calcit::Method(stripped.into(), MethodKind::Access)) diff --git a/src/primes.rs b/src/primes.rs index 33e7fa29..3f7cc3b0 100644 --- a/src/primes.rs +++ b/src/primes.rs @@ -187,12 +187,10 @@ impl fmt::Display for Calcit { Calcit::Tuple(tag, extra, _class) => { let mut extra_str = String::from(""); for item in extra { - if !extra_str.is_empty() { - extra_str.push(' '); - } + extra_str.push(' '); extra_str.push_str(&item.to_string()) } - f.write_str(&format!("(:: {tag} {extra_str})")) + f.write_str(&format!("(:: {tag}{extra_str})")) } Calcit::Buffer(buf) => { f.write_str("(&buffer")?; diff --git a/src/primes/proc_name.rs b/src/primes/proc_name.rs index 596a59f4..5215615a 100644 --- a/src/primes/proc_name.rs +++ b/src/primes/proc_name.rs @@ -30,6 +30,7 @@ pub enum CalcitProc { NativeTupleAssoc, NativeTupleCount, NativeTupleClass, + NativeTupleWithClass, NativeDisplayStack, Raise, Quit, @@ -207,6 +208,7 @@ impl FromStr for CalcitProc { "&tuple:assoc" => Ok(Self::NativeTupleAssoc), "&tuple:count" => Ok(Self::NativeTupleCount), "&tuple:class" => Ok(Self::NativeTupleClass), + "&tuple:with-class" => Ok(Self::NativeTupleWithClass), // effects "&display-stack" => Ok(Self::NativeDisplayStack), "raise" => Ok(Self::Raise), @@ -388,6 +390,7 @@ impl Display for CalcitProc { Self::NativeTupleAssoc => write!(f, "&tuple:assoc"), Self::NativeTupleCount => write!(f, "&tuple:count"), Self::NativeTupleClass => write!(f, "&tuple:class"), + Self::NativeTupleWithClass => write!(f, "&tuple:with-class"), Self::NativeDisplayStack => write!(f, "&display-stack"), Self::Raise => write!(f, "raise"), Self::Quit => write!(f, "quit!"), diff --git a/src/runner.rs b/src/runner.rs index 0093c819..86fb77e2 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -61,7 +61,7 @@ pub fn evaluate_expr(expr: &Calcit, scope: &CalcitScope, file_ns: Arc, call Calcit::Buffer(..) => Ok(expr.to_owned()), Calcit::CirruQuote(..) => Ok(expr.to_owned()), Calcit::Recur(_) => unreachable!("recur not expected to be from symbol"), - Calcit::RawCode(_, code) => unreachable!("native code {} not expected to be evaluated", code), + Calcit::RawCode(_, code) => unreachable!("raw code `{}` cannot be called", code), Calcit::List(xs) => match xs.get(0) { None => Err(CalcitErr::use_msg_stack(format!("cannot evaluate empty expr: {expr}"), call_stack)), Some(x) => { diff --git a/ts-src/calcit.procs.mts b/ts-src/calcit.procs.mts index 10310037..150c31c4 100644 --- a/ts-src/calcit.procs.mts +++ b/ts-src/calcit.procs.mts @@ -1,5 +1,5 @@ // CALCIT VERSION -export const calcit_version = "0.7.0"; +export const calcit_version = "0.7.2"; import { parse, ICirruNode } from "@cirru/parser.ts"; import { writeCirruCode } from "@cirru/writer.ts"; @@ -299,10 +299,17 @@ export let _$n_tuple_$o_count = function (xs: CalcitValue) { }; export let _$n_tuple_$o_class = function (x: CalcitTuple) { - if (arguments.length !== 1) throw new Error("&tuple:class takes 1 arguments"); + if (arguments.length !== 1) throw new Error("&tuple:class takes 1 argument"); return x.klass; }; +export let _$n_tuple_$o_with_class = function (x: CalcitTuple, y: CalcitRecord) { + if (arguments.length !== 2) throw new Error("&tuple:with-class takes 2 arguments"); + if (!(x instanceof CalcitTuple)) throw new Error("&tuple:with-class expects a tuple"); + if (!(y instanceof CalcitRecord)) throw new Error("&tuple:with-class expects second argument in record"); + return new CalcitTuple(x.tag, x.extra, y); +}; + export let _$n_record_$o_get = function (xs: CalcitValue, k: CalcitTag) { if (arguments.length !== 2) { throw new Error("record &get takes 2 arguments");