diff --git a/src/main.rs b/src/main.rs index ed9c9da..ec22849 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,7 +58,12 @@ use crate::base::*; pub fn main() { let src = " -\"thing\" +let foo = :foo +let bar = 42 +let baz = \"foo bar baz\" +let quux = (1, 2, [3, 4, #{:five 6, :seven 8}]) +\"{foo} {bar} {baz} +{quux} {fuzz} TADA!\" "; let (tokens, lex_errs) = lexer().parse(src).into_output_errors(); if !lex_errs.is_empty() { @@ -73,13 +78,13 @@ pub fn main() { let (ast, _) = parser() .parse(Stream::from_iter(to_parse).map((0..src.len()).into(), |(t, s)| (t, s))) .unwrap(); - println!("{}", ast); + // println!("{}", ast); - // let mut ctx = base(); + let mut ctx = base(); - // let result = eval(&ast, &mut ctx).unwrap(); + let result = eval(&ast, &mut ctx).unwrap(); - // println!("{}", result); + println!("{}", result); // struct_scalpel::print_dissection_info::() // struct_scalpel::print_dissection_info::(); diff --git a/src/value.rs b/src/value.rs index f0ab649..87f08d5 100644 --- a/src/value.rs +++ b/src/value.rs @@ -175,3 +175,37 @@ impl<'src> PartialEq for Value<'src> { } impl Eq for Value<'_> {} + +impl Value<'_> { + pub fn interpolate(&self) -> String { + match self { + Value::Nil => String::new(), + Value::Boolean(b) => format!("{b}"), + Value::Number(n) => format!("{n}"), + Value::Keyword(k) => format!(":{k}"), + Value::AllocatedString(s) => format!("{s}"), + Value::InternedString(s) => s.to_string(), + Value::Box(_, x) => x.borrow().interpolate(), + Value::Tuple(xs) => xs + .iter() + .map(|x| x.interpolate()) + .collect::>() + .join(", "), + Value::List(xs) => xs + .iter() + .map(|x| x.interpolate()) + .collect::>() + .join(", "), + Value::Dict(xs) => xs + .iter() + .map(|(k, v)| format!(":{} {}", k, v.interpolate())) + .collect::>() + .join(", "), + Value::Fn(x) => format!("fn {}", x.name.to_string()), + Value::Placeholder => unreachable!(), + Value::Args(_) => unreachable!(), + Value::Recur(_) => unreachable!(), + Value::Base(_) => unreachable!(), + } + } +} diff --git a/src/vm.rs b/src/vm.rs index 14f36a8..5cff0ce 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -282,7 +282,28 @@ pub fn eval<'src, 'a>( Ast::Number(n) => Ok(Value::Number(*n)), Ast::Keyword(k) => Ok(Value::Keyword(k)), Ast::String(s) => Ok(Value::InternedString(s)), - Ast::Interpolated(s) => todo!(), + Ast::Interpolated(parts) => { + let mut interpolated = String::new(); + for part in parts { + match &part.0 { + StringPart::Data(s) => interpolated.push_str(s.as_str()), + StringPart::Word(w) => { + let val = if let Some((_, value)) = + ctx.iter().rev().find(|(name, _)| w == name) + { + value.clone() + } else { + return Err(LudusError { + msg: format!("unbound name {w}"), + }); + }; + interpolated.push_str(val.interpolate().as_str()) + } + StringPart::Inline(_) => unreachable!(), + } + } + Ok(Value::AllocatedString(Rc::new(interpolated))) + } Ast::Block(exprs) => { let to = ctx.len(); let mut result = Value::Nil;