From 54bcacc1171301104a39667812b76842acf2bf5e Mon Sep 17 00:00:00 2001 From: Shane Vandegrift Date: Tue, 23 Apr 2024 15:59:22 -0400 Subject: [PATCH 1/5] add into() for ExprKind into Expr --- stack-core/src/engine.rs | 7 +- stack-core/src/expr.rs | 9 +++ stack-core/src/intrinsic.rs | 134 +++++++++++------------------------- stack-core/src/parser.rs | 3 +- stack-core/tests/_runner.rs | 4 +- stack-std/src/fs.rs | 12 ++-- stack-std/src/scope.rs | 59 ++++------------ stack-std/src/str.rs | 50 +++++--------- 8 files changed, 94 insertions(+), 184 deletions(-) diff --git a/stack-core/src/engine.rs b/stack-core/src/engine.rs index af9e1481..c6004133 100644 --- a/stack-core/src/engine.rs +++ b/stack-core/src/engine.rs @@ -115,10 +115,9 @@ impl Engine { } Ok(context) } else { - context.stack_push(Expr { - kind: ExprKind::Error(Error::new("unknown function".into())), - info: None, - })?; + context.stack_push( + ExprKind::Error(Error::new("unknown function".into())).into(), + )?; Ok(context) } diff --git a/stack-core/src/expr.rs b/stack-core/src/expr.rs index 0f280c1b..d3316450 100644 --- a/stack-core/src/expr.rs +++ b/stack-core/src/expr.rs @@ -13,6 +13,15 @@ pub struct Expr { pub info: Option, } +impl From for Expr { + fn from(value: ExprKind) -> Self { + Self { + info: None, + kind: value, + } + } +} + impl PartialEq for Expr { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/stack-core/src/intrinsic.rs b/stack-core/src/intrinsic.rs index 62d1d048..da68d1f7 100644 --- a/stack-core/src/intrinsic.rs +++ b/stack-core/src/intrinsic.rs @@ -128,7 +128,7 @@ impl Intrinsic { Err(_) => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -142,7 +142,7 @@ impl Intrinsic { Err(_) => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -156,7 +156,7 @@ impl Intrinsic { Err(_) => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -170,7 +170,7 @@ impl Intrinsic { Err(_) => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -184,7 +184,7 @@ impl Intrinsic { Err(_) => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -196,7 +196,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind == rhs.kind); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -207,7 +207,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind != rhs.kind); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -218,7 +218,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind < rhs.kind); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -229,7 +229,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind <= rhs.kind); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -240,7 +240,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind > rhs.kind); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -251,7 +251,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind >= rhs.kind); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -264,7 +264,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind.is_truthy() || rhs.kind.is_truthy()); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -276,7 +276,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(lhs.kind.is_truthy() && rhs.kind.is_truthy()); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -286,7 +286,7 @@ impl Intrinsic { let kind = ExprKind::Boolean(!rhs.kind.is_truthy()); - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -302,10 +302,7 @@ impl Intrinsic { Err(RunError { reason: RunErrorReason::AssertionFailed, context, - expr: Expr { - info: None, - kind: message.kind, - }, + expr: message.kind.into(), }) } } @@ -382,7 +379,7 @@ impl Intrinsic { context.stack_push(item.clone())?; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -408,7 +405,7 @@ impl Intrinsic { context.stack_push(item.clone())?; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -423,25 +420,13 @@ impl Intrinsic { if (i as usize) < x.len() { let rest = x.split_off(i as usize); - context.stack_push(Expr { - kind: ExprKind::List(x), - info: None, - })?; + context.stack_push(ExprKind::List(x).into())?; - context.stack_push(Expr { - kind: ExprKind::List(rest), - info: None, - })?; + context.stack_push(ExprKind::List(rest).into())?; } else { - context.stack_push(Expr { - kind: ExprKind::List(x), - info: None, - })?; + context.stack_push(ExprKind::List(x).into())?; - context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - })?; + context.stack_push(ExprKind::Nil.into())?; } } (ExprKind::String(mut x), ExprKind::Integer(i)) if i >= 0 => { @@ -449,39 +434,21 @@ impl Intrinsic { Some((i, _)) => { let rest = x.split_off(i); - context.stack_push(Expr { - kind: ExprKind::String(x), - info: None, - })?; + context.stack_push(ExprKind::String(x).into())?; - context.stack_push(Expr { - kind: ExprKind::String(rest), - info: None, - })?; + context.stack_push(ExprKind::String(rest).into())?; } None => { - context.stack_push(Expr { - kind: ExprKind::String(x), - info: None, - })?; + context.stack_push(ExprKind::String(x).into())?; - context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - })?; + context.stack_push(ExprKind::Nil.into())?; } } } _ => { - context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - })?; + context.stack_push(ExprKind::Nil.into())?; - context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - })?; + context.stack_push(ExprKind::Nil.into())?; } } @@ -505,7 +472,7 @@ impl Intrinsic { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -539,7 +506,7 @@ impl Intrinsic { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -549,41 +516,23 @@ impl Intrinsic { match list.kind.clone() { ExprKind::List(mut x) => { - let e = x.pop().unwrap_or(Expr { - kind: ExprKind::Nil, - info: None, - }); + let e = x.pop().unwrap_or(ExprKind::Nil.into()); - context.stack_push(Expr { - kind: ExprKind::List(x), - info: list.info, - })?; + context.stack_push(ExprKind::List(x).into())?; context.stack_push(e)?; } ExprKind::String(mut x) => { let e = x .pop() - .map(|e| Expr { - kind: ExprKind::String(e.to_compact_string()), - info: None, - }) - .unwrap_or(Expr { - kind: ExprKind::Nil, - info: None, - }); + .map(|e| ExprKind::String(e.to_compact_string()).into()) + .unwrap_or(ExprKind::Nil.into()); - context.stack_push(Expr { - kind: ExprKind::String(x), - info: list.info, - })?; + context.stack_push(ExprKind::String(x).into())?; context.stack_push(e)?; } _ => { context.stack_push(list.clone())?; - context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - })?; + context.stack_push(ExprKind::Nil.into())?; } } @@ -885,7 +834,7 @@ impl Intrinsic { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) } @@ -894,10 +843,7 @@ impl Intrinsic { Self::Lazy => { let expr = context.stack_pop(&expr)?; - context.stack_push(Expr { - kind: ExprKind::Lazy(Box::new(expr)), - info: None, - })?; + context.stack_push(ExprKind::Lazy(Box::new(expr)).into())?; Ok(context) } @@ -1055,10 +1001,8 @@ impl Intrinsic { // MARK: Recur // Functionality is implemented in [`Engine::call_fn`] Self::Recur => { - context.stack_push(Expr { - kind: ExprKind::Symbol(Symbol::from_ref("recur")), - info: None, - })?; + context + .stack_push(ExprKind::Symbol(Symbol::from_ref("recur")).into())?; Ok(context) } diff --git a/stack-core/src/parser.rs b/stack-core/src/parser.rs index ed5ee067..9f8e35eb 100644 --- a/stack-core/src/parser.rs +++ b/stack-core/src/parser.rs @@ -1,8 +1,7 @@ +use compact_str::ToCompactString; use core::fmt; use std::collections::HashMap; -use compact_str::ToCompactString; - use crate::{ expr::{Expr, ExprInfo, ExprKind, FnIdent}, lexer::{Lexer, Span, Token, TokenKind}, diff --git a/stack-core/tests/_runner.rs b/stack-core/tests/_runner.rs index e974ecf8..ce812c6a 100644 --- a/stack-core/tests/_runner.rs +++ b/stack-core/tests/_runner.rs @@ -5,8 +5,8 @@ use stack_core::prelude::*; use test_case::case; #[inline] -const fn e(kind: ExprKind) -> Expr { - Expr { kind, info: None } +fn e(kind: ExprKind) -> Expr { + kind.into() } // TODO: Add tests for missing intrinsics. diff --git a/stack-std/src/fs.rs b/stack-std/src/fs.rs index f1e7db24..cdde12e3 100644 --- a/stack-std/src/fs.rs +++ b/stack-std/src/fs.rs @@ -7,16 +7,16 @@ pub fn module(sandbox: bool) -> Module { if !sandbox { module .add_func(Symbol::from_ref("cwd"), |_, mut context, _| { - context.stack_push(Expr { - kind: std::env::current_dir() + context.stack_push( + std::env::current_dir() .map(|x| { ExprKind::String( x.to_string_lossy().into_owned().to_compact_string(), ) }) - .unwrap_or(ExprKind::Nil), - info: None, - })?; + .unwrap_or(ExprKind::Nil) + .into(), + )?; Ok(context) }) @@ -31,7 +31,7 @@ pub fn module(sandbox: bool) -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }); diff --git a/stack-std/src/scope.rs b/stack-std/src/scope.rs index b340db91..835588fe 100644 --- a/stack-std/src/scope.rs +++ b/stack-std/src/scope.rs @@ -12,41 +12,23 @@ pub fn module() -> Module { match symbol.kind { ExprKind::Symbol(ref x) => { if Intrinsic::from_str(x.as_str()).is_ok() { - context.stack_push(Expr { - kind: ExprKind::String("intrinsic".into()), - info: None, - }) + context.stack_push(ExprKind::String("intrinsic".into()).into()) } else if engine .module(&Symbol::new( x.as_str().split(':').next().unwrap_or_default().into(), )) .is_some() { - context.stack_push(Expr { - kind: ExprKind::String("module".into()), - info: None, - }) + context.stack_push(ExprKind::String("module".into()).into()) } else if context.let_get(*x).is_some() { - context.stack_push(Expr { - kind: ExprKind::String("let".into()), - info: None, - }) + context.stack_push(ExprKind::String("let".into()).into()) } else if context.scope_item(*x).is_some() { - context.stack_push(Expr { - kind: ExprKind::String("scope".into()), - info: None, - }) + context.stack_push(ExprKind::String("scope".into()).into()) } else { - context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - }) + context.stack_push(ExprKind::Nil.into()) } } - _ => context.stack_push(Expr { - kind: ExprKind::Nil, - info: None, - }), + _ => context.stack_push(ExprKind::Nil.into()), } .map(|_| context) }) @@ -55,32 +37,21 @@ pub fn module() -> Module { .scope_items() .map(|(name, content)| { let list: Vec = vec![ - Expr { - kind: ExprKind::Symbol(*name), - info: None, - }, - Expr { - kind: content - .borrow() - .val() - .map(|e| e.kind) - .unwrap_or(ExprKind::Nil), - info: None, - }, + ExprKind::Symbol(*name).into(), + content + .borrow() + .val() + .map(|e| e.kind) + .unwrap_or(ExprKind::Nil) + .into(), ]; - Expr { - kind: ExprKind::List(list), - info: None, - } + ExprKind::List(list).into() }) .collect(); context - .stack_push(Expr { - kind: ExprKind::List(items), - info: None, - }) + .stack_push(ExprKind::List(items).into()) .map(|_| context) }); diff --git a/stack-std/src/str.rs b/stack-std/src/str.rs index b9a6cc69..5a08851e 100644 --- a/stack-std/src/str.rs +++ b/stack-std/src/str.rs @@ -14,7 +14,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -26,7 +26,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -38,7 +38,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -53,7 +53,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -68,7 +68,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -79,16 +79,13 @@ pub fn module() -> Module { let kind = match (item.kind.clone(), patt.kind.clone()) { (ExprKind::String(ref x), ExprKind::String(ref y)) => ExprKind::List( x.split(y.as_str()) - .map(|x| Expr { - kind: ExprKind::String(x.into()), - info: None, - }) + .map(|x| ExprKind::String(x.into()).into()) .collect(), ), _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -100,16 +97,13 @@ pub fn module() -> Module { let kind = match item.kind { ExprKind::String(ref x) => ExprKind::List( x.split_whitespace() - .map(|x| Expr { - kind: ExprKind::String(x.into()), - info: None, - }) + .map(|x| ExprKind::String(x.into()).into()) .collect(), ), _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }, @@ -122,7 +116,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -134,7 +128,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -146,7 +140,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -160,7 +154,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -172,16 +166,13 @@ pub fn module() -> Module { x.as_bytes() .iter() .copied() - .map(|x| Expr { - kind: ExprKind::Integer(x as i64), - info: None, - }) + .map(|x| ExprKind::Integer(x as i64).into()) .collect(), ), _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -207,7 +198,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -218,16 +209,13 @@ pub fn module() -> Module { ExprKind::String(ref x) => ExprKind::List( x.as_str() .graphemes(true) - .map(|x| Expr { - kind: ExprKind::String(x.into()), - info: None, - }) + .map(|x| ExprKind::String(x.into()).into()) .collect(), ), _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) @@ -250,7 +238,7 @@ pub fn module() -> Module { _ => ExprKind::Nil, }; - context.stack_push(Expr { kind, info: None })?; + context.stack_push(kind.into())?; Ok(context) }) From db0c4df6aacc7d927f7995e97a0daab4e4a82703 Mon Sep 17 00:00:00 2001 From: Shane Vandegrift Date: Tue, 23 Apr 2024 16:06:06 -0400 Subject: [PATCH 2/5] implement tags onto expressions --- stack-core/src/expr.rs | 19 +++++++++++++++++++ stack-core/src/intrinsic.rs | 5 +---- stack-core/src/parser.rs | 8 +++++++- stack-core/src/scope.rs | 29 +++++++++++++++++------------ 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/stack-core/src/expr.rs b/stack-core/src/expr.rs index d3316450..dff86c2d 100644 --- a/stack-core/src/expr.rs +++ b/stack-core/src/expr.rs @@ -11,6 +11,19 @@ use crate::{lexer::Span, scope::Scope, source::Source, symbol::Symbol}; pub struct Expr { pub kind: ExprKind, pub info: Option, + pub tags: HashMap, +} + +impl Expr { + pub fn with_tags(mut self, tags: HashMap) -> Self { + self.tags = tags; + self + } + + pub fn with_info(mut self, info: Option) -> Self { + self.info = info; + self + } } impl From for Expr { @@ -18,6 +31,7 @@ impl From for Expr { Self { info: None, kind: value, + tags: HashMap::new(), } } } @@ -66,6 +80,11 @@ pub enum ExprKind { } impl ExprKind { + #[inline] + pub fn into_expr(self) -> Expr { + self.into() + } + #[inline] pub const fn is_nil(&self) -> bool { matches!(self, Self::Nil) diff --git a/stack-core/src/intrinsic.rs b/stack-core/src/intrinsic.rs index da68d1f7..bbf7fc35 100644 --- a/stack-core/src/intrinsic.rs +++ b/stack-core/src/intrinsic.rs @@ -483,10 +483,7 @@ impl Intrinsic { let kind = match (list.kind.clone(), item.kind.clone()) { (ExprKind::List(mut x), i) => { - x.push(Expr { - kind: i, - info: item.info.clone(), - }); + x.push(i.into_expr().with_info(item.info)); ExprKind::List(x) } (ExprKind::String(mut x), ExprKind::String(s)) => { diff --git a/stack-core/src/parser.rs b/stack-core/src/parser.rs index 9f8e35eb..12dfa3fb 100644 --- a/stack-core/src/parser.rs +++ b/stack-core/src/parser.rs @@ -48,6 +48,7 @@ fn parse_expr(lexer: &mut Lexer) -> Result { end: next_token.span.end, }, }), + tags: HashMap::new(), }) } TokenKind::LeftParen => { @@ -62,6 +63,7 @@ fn parse_expr(lexer: &mut Lexer) -> Result { end: end_span.end, }, }), + tags: HashMap::new(), }) } @@ -93,6 +95,7 @@ fn parse_expr(lexer: &mut Lexer) -> Result { source, span: token.span, }), + tags: HashMap::new(), }) } TokenKind::Float => { @@ -108,6 +111,7 @@ fn parse_expr(lexer: &mut Lexer) -> Result { source, span: token.span, }), + tags: HashMap::new(), }) } TokenKind::String => { @@ -127,6 +131,7 @@ fn parse_expr(lexer: &mut Lexer) -> Result { source, span: token.span, }), + tags: HashMap::new(), }) } TokenKind::Symbol => { @@ -151,6 +156,7 @@ fn parse_expr(lexer: &mut Lexer) -> Result { source, span: token.span, }), + tags: HashMap::new(), }) } } @@ -264,7 +270,7 @@ mod test { } #[case("" => Ok(Vec::::new()) ; "empty")] - #[case("1" => Ok(vec![Expr { kind: ExprKind::Integer(1), info: Some(ExprInfo { source: s("1"), span: Span { start: 0, end: 1 } }) }]))] + #[case("1" => Ok(vec![Expr { kind: ExprKind::Integer(1), info: Some(ExprInfo { source: s("1"), span: Span { start: 0, end: 1 } }), tags: HashMap::new() }]))] fn parse(source: &str) -> Result, ParseError> { let mut lexer = Lexer::new(s(source)); super::parse(&mut lexer) diff --git a/stack-core/src/scope.rs b/stack-core/src/scope.rs index b96ca3ad..a240d21f 100644 --- a/stack-core/src/scope.rs +++ b/stack-core/src/scope.rs @@ -144,10 +144,13 @@ impl<'s> Scanner<'s> { let mut scanner = Scanner::new(&mut duplicate); let unlazied_mut = item.kind.unlazy_mut(); *unlazied_mut = scanner - .scan(Expr { - kind: unlazied_mut.clone(), - info: item.info.clone(), - }) + .scan( + unlazied_mut + .clone() + .into_expr() + .with_info(item.info.clone()) + .with_tags(item.tags.clone()), + ) .unwrap() .kind } @@ -161,18 +164,20 @@ impl<'s> Scanner<'s> { scoped: fn_symbol.scoped, }); - let mut list_items = vec![Expr { - kind: fn_ident, - info: expr.info.clone(), - }]; + let mut list_items = vec![fn_ident + .into_expr() + .with_info(expr.info.clone()) + .with_tags(expr.tags.clone())]; list_items.extend(fn_body); let new_expr = ExprKind::List(list_items); - Ok(Expr { - kind: new_expr, - info: expr.info, - }) + Ok( + new_expr + .into_expr() + .with_info(expr.info) + .with_tags(expr.tags), + ) } else { // If the expression is not a function, we just return it Ok(expr) From a1085576656ac6bfa642418a8a32c3dd93ef7f63 Mon Sep 17 00:00:00 2001 From: Shane Vandegrift Date: Tue, 23 Apr 2024 16:10:16 -0400 Subject: [PATCH 3/5] implement casting exprkinds to symbols --- stack-core/src/symbol.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stack-core/src/symbol.rs b/stack-core/src/symbol.rs index 734bd216..951c2091 100644 --- a/stack-core/src/symbol.rs +++ b/stack-core/src/symbol.rs @@ -3,6 +3,8 @@ use core::{borrow::Borrow, fmt, hash::Hash}; use compact_str::CompactString; use internment::Intern; +use crate::expr::ExprKind; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct Symbol(Intern); @@ -36,3 +38,9 @@ impl fmt::Display for Symbol { write!(f, "{}", self.as_str()) } } + +impl From for Symbol { + fn from(value: ExprKind) -> Self { + Self::from_ref(value.to_string().as_str()) + } +} From 16272ea44359dc81176eef071db945dedabf24d8 Mon Sep 17 00:00:00 2001 From: Shane Vandegrift Date: Tue, 23 Apr 2024 16:19:01 -0400 Subject: [PATCH 4/5] add tag module --- stack-cli/src/main.rs | 8 ++++++++ stack-std/src/lib.rs | 1 + stack-std/src/tag.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 stack-std/src/tag.rs diff --git a/stack-cli/src/main.rs b/stack-cli/src/main.rs index 318a5805..c0d0dd1f 100644 --- a/stack-cli/src/main.rs +++ b/stack-cli/src/main.rs @@ -51,6 +51,10 @@ fn main() { if cli.enable_all || cli.enable_scope { engine.add_module(stack_std::scope::module()); } + + if cli.enable_all || cli.enable_tag { + engine.add_module(stack_std::tag::module()); + } } match cli.subcommand { @@ -307,6 +311,10 @@ struct Cli { #[arg(long)] #[cfg(feature = "stack-std")] enable_scope: bool, + /// Enable the tag standard module. + #[arg(long)] + #[cfg(feature = "stack-std")] + enable_tag: bool, } #[derive(Debug, Clone, PartialEq, Eq, Default, clap::Subcommand)] diff --git a/stack-std/src/lib.rs b/stack-std/src/lib.rs index 4e0ac303..6c117983 100644 --- a/stack-std/src/lib.rs +++ b/stack-std/src/lib.rs @@ -1,3 +1,4 @@ pub mod fs; pub mod scope; pub mod str; +pub mod tag; diff --git a/stack-std/src/tag.rs b/stack-std/src/tag.rs new file mode 100644 index 00000000..2f596f1b --- /dev/null +++ b/stack-std/src/tag.rs @@ -0,0 +1,42 @@ +use stack_core::prelude::*; + +pub fn module() -> Module { + Module::new(Symbol::from_ref("tag")) + .with_func(Symbol::from_ref("add"), |_, mut context, expr| { + let item = context.stack_pop(&expr)?; + let value = context.stack_pop(&expr)?; + let key = context.stack_pop(&expr)?; + + let mut clone = item.clone(); + clone.tags.insert(key.kind.into(), value); + + context.stack_push(clone)?; + + Ok(context) + }) + .with_func(Symbol::from_ref("remove"), |_, mut context, expr| { + let item = context.stack_pop(&expr)?; + let key = context.stack_pop(&expr)?; + + let mut clone = item.clone(); + clone.tags.remove(&key.kind.into()); + + context.stack_push(clone)?; + + Ok(context) + }) + .with_func(Symbol::from_ref("get"), |_, mut context, expr| { + let item = context.stack_pop(&expr)?; + let key = context.stack_pop(&expr)?; + + let result = match item.tags.get(&key.kind.into()) { + Some(expr) => expr.clone(), + None => ExprKind::Nil.into(), + }; + + context.stack_push(item)?; + context.stack_push(result)?; + + Ok(context) + }) +} From 6f3b45983d7499e6ad436b5d8a68c0eaf32ee2b6 Mon Sep 17 00:00:00 2001 From: Shane Vandegrift Date: Tue, 23 Apr 2024 20:57:19 -0400 Subject: [PATCH 5/5] use compact string --- stack-core/src/symbol.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stack-core/src/symbol.rs b/stack-core/src/symbol.rs index 951c2091..56b66fe2 100644 --- a/stack-core/src/symbol.rs +++ b/stack-core/src/symbol.rs @@ -1,6 +1,6 @@ use core::{borrow::Borrow, fmt, hash::Hash}; -use compact_str::CompactString; +use compact_str::{CompactString, ToCompactString}; use internment::Intern; use crate::expr::ExprKind; @@ -41,6 +41,6 @@ impl fmt::Display for Symbol { impl From for Symbol { fn from(value: ExprKind) -> Self { - Self::from_ref(value.to_string().as_str()) + Self::from_ref(value.to_compact_string().as_str()) } }