From 1e4aea319faf4157d03c9a415c498437dad79221 Mon Sep 17 00:00:00 2001 From: Arthur Paulino Date: Fri, 17 Nov 2023 19:06:55 -0300 Subject: [PATCH] create and use more idiomatic APIs for LEM types (#902) --- src/lem/eval.rs | 119 +++++++++++++++++----------------------------- src/lem/macros.rs | 81 +++++++++++++------------------ src/lem/mod.rs | 33 ++++++++++--- 3 files changed, 104 insertions(+), 129 deletions(-) diff --git a/src/lem/eval.rs b/src/lem/eval.rs index 881c296330..6eccf94692 100644 --- a/src/lem/eval.rs +++ b/src/lem/eval.rs @@ -355,14 +355,8 @@ fn run_cproc(cproc_sym: Symbol, arity: usize) -> Func { let cproc_name = Var::new("cproc_name"); let cproc_out = vec![expr.clone(), env.clone(), cont.clone()]; let func_out = vec![expr, env.clone(), cont.clone()]; - let err_block = Block { - ops: vec![], - ctrl: ctrl!(return (evaluated_args_cp, env, err)), - }; - let def_block = Block { - ops: vec![], - ctrl: ctrl!(return (cproc, env, cont)), - }; + let err_block = Block::ctrl(ctrl!(return (evaluated_args_cp, env, err))); + let def_block = Block::ctrl(ctrl!(return (cproc, env, cont))); let mut cproc_inp = (0..arity) .map(|i| Var(format!("x{i}").into())) .collect::>(); @@ -381,17 +375,14 @@ fn run_cproc(cproc_sym: Symbol, arity: usize) -> Func { ), Op::EqTag(is_nil.clone(), evaluated_args.clone(), nil.clone()), ]; - block = if i == 0 { - Block { - ops, - ctrl: Ctrl::If(is_nil.clone(), Box::new(block), Box::new(err_block.clone())), - } - } else { - Block { - ops, - ctrl: Ctrl::If(is_nil.clone(), Box::new(err_block.clone()), Box::new(block)), - } - } + block = Block { + ops, + ctrl: if i == 0 { + Ctrl::if_(is_nil.clone(), block, err_block.clone()) + } else { + Ctrl::if_(is_nil.clone(), err_block.clone(), block) + }, + }; } if arity > 0 { let ops = vec![ @@ -400,28 +391,24 @@ fn run_cproc(cproc_sym: Symbol, arity: usize) -> Func { ]; block = Block { ops, - ctrl: Ctrl::If(is_nil.clone(), Box::new(err_block.clone()), Box::new(block)), + ctrl: Ctrl::if_(is_nil.clone(), err_block.clone(), block), } } // MatchSymbol - let mut match_symbol_map = IndexMap::with_capacity(1); - match_symbol_map.insert(cproc_sym, block); block = Block { ops: vec![Op::Decons2( [cproc_name.clone(), evaluated_args], cproc.clone(), )], - ctrl: Ctrl::MatchSymbol( + ctrl: Ctrl::match_symbol( cproc_name, - match_symbol_map, - Some(Box::new(def_block.clone())), + vec![(cproc_sym, block)], + Some(def_block.clone()), ), }; // MatchTag - let mut match_tag_map = IndexMap::with_capacity(1); - match_tag_map.insert(Tag::Expr(Cproc), block); block = Block { ops: if arity == 0 { vec![] @@ -432,7 +419,11 @@ fn run_cproc(cproc_sym: Symbol, arity: usize) -> Func { op!(let nil = cast(nil, Expr::Nil)), ] }, - ctrl: Ctrl::MatchTag(cproc.clone(), match_tag_map, Some(Box::new(def_block))), + ctrl: Ctrl::match_tag( + cproc.clone(), + vec![(Tag::Expr(Cproc), block)], + Some(def_block), + ), }; let func_inp = vec![cproc, env, cont]; Func::new("run_cproc".into(), func_inp, 3, block).unwrap() @@ -482,21 +473,12 @@ fn is_cproc(cprocs: &[(&Symbol, usize)]) -> Func { op!(let nil = cast(nil, Expr::Nil)), op!(let t = Symbol("t")), ]; - let mut match_symbol_map = IndexMap::with_capacity(cprocs.len()); - for (cproc, _) in cprocs { - match_symbol_map.insert( - (*cproc).clone(), - Block { - ops: vec![], - ctrl: ctrl!(return (t)), - }, - ); - } - let def = Some(Box::new(Block { - ops: vec![], - ctrl: ctrl!(return (nil)), - })); - let ctrl = Ctrl::MatchSymbol(head.clone(), match_symbol_map, def); + let match_symbol_cases = cprocs + .iter() + .map(|(cproc, _)| ((*cproc).clone(), Block::ctrl(ctrl!(return (t))))) + .collect(); + let def = Some(Block::ctrl(ctrl!(return (nil)))); + let ctrl = Ctrl::match_symbol(head.clone(), match_symbol_cases, def); Func::new("is_cproc".into(), vec![head], 1, Block { ops, ctrl }).unwrap() } } @@ -571,28 +553,16 @@ fn match_and_run_cproc(cprocs: &[(&Symbol, usize)]) -> Func { let is_nil = Var::new("is_nil"); let cproc_out = vec![expr.clone(), env.clone(), cont.clone()]; let func_out = vec![expr, env.clone(), cont.clone(), Var::new("makethunk")]; - let err_block = Block { - ops: vec![], - ctrl: ctrl!(return (evaluated_args_cp, env, err, errctrl)), - }; - let err_block_from_cproc = Block { - ops: vec![], - ctrl: ctrl!(return (expr, env, err, errctrl)), - }; - let ret_block_from_cproc = Block { - ops: vec![], - ctrl: ctrl!(return (expr, env, cont, ret)), - }; - let mut check_cproc_error_map = IndexMap::with_capacity(2); - check_cproc_error_map.insert(Tag::Cont(Error), err_block_from_cproc); - check_cproc_error_map.insert(Tag::Cont(Terminal), ret_block_from_cproc); - let check_cproc_error_ctrl = Ctrl::MatchTag( + let err_block = Block::ctrl(ctrl!(return (evaluated_args_cp, env, err, errctrl))); + let err_block_from_cproc = Block::ctrl(ctrl!(return (expr, env, err, errctrl))); + let ret_block_from_cproc = Block::ctrl(ctrl!(return (expr, env, cont, ret))); + let check_cproc_error_ctrl = Ctrl::match_tag( cont.clone(), - check_cproc_error_map, - Some(Box::new(Block { - ops: vec![], - ctrl: Ctrl::Return(func_out), - })), + vec![ + (Tag::Cont(Error), err_block_from_cproc), + (Tag::Cont(Terminal), ret_block_from_cproc), + ], + Some(Block::ctrl(Ctrl::Return(func_out))), ); let mut match_symbol_map = IndexMap::with_capacity(cprocs.len()); for (cproc, arity) in cprocs { @@ -620,17 +590,14 @@ fn match_and_run_cproc(cprocs: &[(&Symbol, usize)]) -> Func { ), Op::EqTag(is_nil.clone(), evaluated_args.clone(), nil.clone()), ]; - block = if i == 0 { - Block { - ops, - ctrl: Ctrl::If(is_nil.clone(), Box::new(block), Box::new(err_block.clone())), - } - } else { - Block { - ops, - ctrl: Ctrl::If(is_nil.clone(), Box::new(err_block.clone()), Box::new(block)), - } - } + block = Block { + ops, + ctrl: if i == 0 { + Ctrl::if_(is_nil.clone(), block, err_block.clone()) + } else { + Ctrl::if_(is_nil.clone(), err_block.clone(), block) + }, + }; } if arity > 0 { let ops = vec![ @@ -639,7 +606,7 @@ fn match_and_run_cproc(cprocs: &[(&Symbol, usize)]) -> Func { ]; block = Block { ops, - ctrl: Ctrl::If(is_nil.clone(), Box::new(err_block.clone()), Box::new(block)), + ctrl: Ctrl::if_(is_nil.clone(), err_block.clone(), block), } } match_symbol_map.insert(cproc.clone(), block); diff --git a/src/lem/macros.rs b/src/lem/macros.rs index e45e81a077..7e16a6a720 100644 --- a/src/lem/macros.rs +++ b/src/lem/macros.rs @@ -692,47 +692,33 @@ mod tests { lem::{Block, Ctrl, Op, Tag, Var}, state::lurk_sym, tag::ExprTag::{Char, Num, Str}, - Symbol, }; #[inline] - fn mptr(name: &str) -> Var { - Var(name.into()) - } - - #[inline] - fn match_tag(i: Var, cases: Vec<(Tag, Block)>) -> Ctrl { - Ctrl::MatchTag(i, indexmap::IndexMap::from_iter(cases), None) - } - - #[inline] - fn match_symbol(i: Var, cases: Vec<(Symbol, Block)>, def: Block) -> Ctrl { - Ctrl::MatchSymbol(i, indexmap::IndexMap::from_iter(cases), Some(Box::new(def))) + fn var(name: &str) -> Var { + Var::new(name) } #[test] fn test_macros() { let lemops = [ - Op::Zero(mptr("foo"), Tag::Expr(Num)), - Op::Cons2(mptr("foo"), Tag::Expr(Char), [mptr("bar"), mptr("baz")]), + Op::Zero(var("foo"), Tag::Expr(Num)), + Op::Cons2(var("foo"), Tag::Expr(Char), [var("bar"), var("baz")]), Op::Cons3( - mptr("foo"), + var("foo"), Tag::Expr(Char), - [mptr("bar"), mptr("baz"), mptr("bazz")], + [var("bar"), var("baz"), var("bazz")], ), Op::Cons4( - mptr("foo"), + var("foo"), Tag::Expr(Char), - [mptr("bar"), mptr("baz"), mptr("bazz"), mptr("baxx")], - ), - Op::Decons2([mptr("foo"), mptr("goo")], mptr("aaa")), - Op::Decons3([mptr("foo"), mptr("goo"), mptr("moo")], mptr("aaa")), - Op::Decons4( - [mptr("foo"), mptr("goo"), mptr("moo"), mptr("noo")], - mptr("aaa"), + [var("bar"), var("baz"), var("bazz"), var("baxx")], ), - Op::Hide(mptr("bar"), mptr("baz"), mptr("bazz")), - Op::Open(mptr("bar"), mptr("baz"), mptr("bazz")), + Op::Decons2([var("foo"), var("goo")], var("aaa")), + Op::Decons3([var("foo"), var("goo"), var("moo")], var("aaa")), + Op::Decons4([var("foo"), var("goo"), var("moo"), var("noo")], var("aaa")), + Op::Hide(var("bar"), var("baz"), var("bazz")), + Op::Open(var("bar"), var("baz"), var("bazz")), ]; let lemops_macro = vec![ op!(let foo: Expr::Num), @@ -750,7 +736,7 @@ mod tests { assert!(lemops[i] == lemops_macro[i]); } - let ret = Ctrl::Return(vec![mptr("bar"), mptr("baz"), mptr("bazz")]); + let ret = Ctrl::Return(vec![var("bar"), var("baz"), var("bazz")]); let block = Block { ops: lemops_macro, ctrl: ret, @@ -785,34 +771,35 @@ mod tests { } }); assert!( - foo == match_tag( - mptr("www"), + foo == Ctrl::match_tag( + var("www"), vec![ ( Tag::Expr(Num), Block { ops: vec![], - ctrl: Ctrl::Return(vec![mptr("foo"), mptr("foo"), mptr("foo")]), + ctrl: Ctrl::Return(vec![var("foo"), var("foo"), var("foo")]), } ), ( Tag::Expr(Str), Block { - ops: vec![Op::Zero(mptr("foo"), Tag::Expr(Num))], - ctrl: Ctrl::Return(vec![mptr("foo"), mptr("foo"), mptr("foo")]), + ops: vec![Op::Zero(var("foo"), Tag::Expr(Num))], + ctrl: Ctrl::Return(vec![var("foo"), var("foo"), var("foo")]), } ), ( Tag::Expr(Char), Block { ops: vec![ - Op::Zero(mptr("foo"), Tag::Expr(Num)), - Op::Zero(mptr("goo"), Tag::Expr(Char)) + Op::Zero(var("foo"), Tag::Expr(Num)), + Op::Zero(var("goo"), Tag::Expr(Char)) ], - ctrl: Ctrl::Return(vec![mptr("foo"), mptr("goo"), mptr("goo")]), + ctrl: Ctrl::Return(vec![var("foo"), var("goo"), var("goo")]), } ) - ] + ], + None, ) ); @@ -832,31 +819,31 @@ mod tests { ); assert!( - moo == match_symbol( - mptr("www"), + moo == Ctrl::match_symbol( + var("www"), vec![ ( lurk_sym("nil"), Block { ops: vec![], - ctrl: Ctrl::Return(vec![mptr("foo"), mptr("foo"), mptr("foo")]), + ctrl: Ctrl::Return(vec![var("foo"), var("foo"), var("foo")]), } ), ( lurk_sym("cons"), Block { ops: vec![ - Op::Zero(mptr("foo"), Tag::Expr(Num)), - Op::Zero(mptr("goo"), Tag::Expr(Char)) + Op::Zero(var("foo"), Tag::Expr(Num)), + Op::Zero(var("goo"), Tag::Expr(Char)) ], - ctrl: Ctrl::Return(vec![mptr("foo"), mptr("goo"), mptr("goo")]), + ctrl: Ctrl::Return(vec![var("foo"), var("goo"), var("goo")]), } ) ], - Block { - ops: vec![Op::Zero(mptr("xoo"), Tag::Expr(Str))], - ctrl: Ctrl::Return(vec![mptr("xoo"), mptr("xoo"), mptr("xoo")]), - } + Some(Block { + ops: vec![Op::Zero(var("xoo"), Tag::Expr(Str))], + ctrl: Ctrl::Return(vec![var("xoo"), var("xoo"), var("xoo")]), + }) ) ); } diff --git a/src/lem/mod.rs b/src/lem/mod.rs index ff5ea11f76..8d1385f837 100644 --- a/src/lem/mod.rs +++ b/src/lem/mod.rs @@ -200,6 +200,16 @@ impl Var { pub fn name(&self) -> &AString { &self.0 } + + #[inline] + pub fn new(name: &str) -> Self { + Self(name.into()) + } + + fn make_unique(&self, uniq: &mut usize) -> Var { + *uniq += 1; + Var(format!("{}#{}", self.name(), uniq).into()) + } } /// A block is a sequence of operations followed by a control. Each block @@ -780,16 +790,27 @@ impl Block { }; Ok(Block { ops, ctrl }) } + + /// Creates a `Block` with an empty vector of `Op`s + #[inline] + fn ctrl(ctrl: Ctrl) -> Block { + Block { ops: vec![], ctrl } + } } -impl Var { +impl Ctrl { #[inline] - pub fn new(name: &str) -> Self { - Self(name.into()) + fn if_(v: Var, true_block: Block, false_block: Block) -> Ctrl { + Ctrl::If(v, true_block.into(), false_block.into()) } - fn make_unique(&self, uniq: &mut usize) -> Var { - *uniq += 1; - Var(format!("{}#{}", self.name(), uniq).into()) + #[inline] + fn match_tag(v: Var, cases: Vec<(Tag, Block)>, def: Option) -> Ctrl { + Ctrl::MatchTag(v, IndexMap::from_iter(cases), def.map(|b| b.into())) + } + + #[inline] + fn match_symbol(v: Var, cases: Vec<(Symbol, Block)>, def: Option) -> Ctrl { + Ctrl::MatchSymbol(v, IndexMap::from_iter(cases), def.map(|b| b.into())) } }