From 5e7592753a5f63eea76a4c589822618c15ab0301 Mon Sep 17 00:00:00 2001 From: Master-Bw3 Date: Tue, 25 Jul 2023 10:59:05 -0500 Subject: [PATCH] macro embedding stuff --- readme.md | 43 +++++++++++ src/interpreter.rs | 15 ++-- src/interpreter/ops.rs | 5 +- src/parse_config.rs | 2 + src/parser.rs | 163 ++++++++++++++++++++++++++++------------- 5 files changed, 168 insertions(+), 60 deletions(-) diff --git a/readme.md b/readme.md index 3dd3c33..aac43b3 100644 --- a/readme.md +++ b/readme.md @@ -122,6 +122,49 @@ if {<\True>} then { ... } Hermes' Gambit //evaluates the 'then' branch + + +``` + +### Macros +Macros are defined using this syntax: +``` +#define Macro Name (DIRECTION signature) ... { +... +} +``` +As an example: +``` +#define Duplicate Thrice (SOUTH_EAST edd) = num, num -> num { + Numerical Reflection: 3 + Gemini Gambit +} +``` + +Note: everything between the signature and first curly bracket is ignored, so the following is also valid: +``` +#define Duplicate Thrice (SOUTH_EAST edd) +{ + Numerical Reflection: 3 + Gemini Gambit +} +``` + +When macros are used in a hex, they get expanded, not evaluated. +``` +Mind's Reflection +Duplicate Thrice //expand a macro + +{ + Duplicate Thrice //expand a macro into a list +} + + + + +<\Duplicate Thrice> //embed the pattern associated with the macro + + //will cause a mishap ``` ## Config diff --git a/src/interpreter.rs b/src/interpreter.rs index 51ef52b..db66c2d 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -123,7 +123,7 @@ fn interpret_node<'a>( Ok(state) } AstNode::Op { name, arg, line } => { - interpret_op(name, arg, state, pattern_registry).map_err(|err| (err, line)) + interpret_op(name, arg, state, pattern_registry, macros).map_err(|err| (err, line)) } AstNode::IfBlock { condition, @@ -145,7 +145,7 @@ fn interpret_node<'a>( calc_buffer_depth(pattern_registry, &Some(buffer.clone())), &mut state.heap, pattern_registry, - macros + macros, )? .iter() .map(|x| (x.clone(), false)) @@ -183,6 +183,7 @@ pub fn interpret_op<'a>( arg: Option, state: &'a mut State, pattern_registry: &PatternRegistry, + macros: &Macros, ) -> Result<&'a mut State, Mishap> { if state.consider_next { return Err(Mishap::OpCannotBeConsidered); @@ -228,15 +229,17 @@ pub fn interpret_op<'a>( crate::parser::OpName::Store => store(&arg, state, false), crate::parser::OpName::Copy => store(&arg, state, true), crate::parser::OpName::Push => push(&arg, state), - crate::parser::OpName::Embed => embed(&arg, state, pattern_registry, EmbedType::Normal), + crate::parser::OpName::Embed => { + embed(&arg, state, pattern_registry, EmbedType::Normal, macros) + } crate::parser::OpName::SmartEmbed => { - embed(&arg, state, pattern_registry, EmbedType::Smart) + embed(&arg, state, pattern_registry, EmbedType::Smart, macros) } crate::parser::OpName::ConsiderEmbed => { - embed(&arg, state, pattern_registry, EmbedType::Consider) + embed(&arg, state, pattern_registry, EmbedType::Consider, macros) } crate::parser::OpName::IntroEmbed => { - embed(&arg, state, pattern_registry, EmbedType::IntroRetro) + embed(&arg, state, pattern_registry, EmbedType::IntroRetro, macros) } }?; } diff --git a/src/interpreter/ops.rs b/src/interpreter/ops.rs index 9538cfe..f1b5b1e 100644 --- a/src/interpreter/ops.rs +++ b/src/interpreter/ops.rs @@ -10,7 +10,7 @@ use crate::{ }, Iota, }, - parser::OpValue, + parser::{OpValue, Macros}, pattern_registry::{PatternRegistry, PatternRegistryExt}, }; @@ -149,6 +149,7 @@ pub fn embed<'a>( state: &'a mut State, pattern_registry: &PatternRegistry, embed_type: EmbedType, + macros: &Macros ) -> Result<(), Mishap> { let val = match value { Some(val) => val, @@ -167,7 +168,7 @@ pub fn embed<'a>( *pat.value.clone(), state, pattern_registry, - &HashMap::new(), + macros, None, ) .map_err(|err| err.0)?; diff --git a/src/parse_config.rs b/src/parse_config.rs index 37351b4..a582d1f 100644 --- a/src/parse_config.rs +++ b/src/parse_config.rs @@ -71,6 +71,7 @@ fn parse_library(library: &mut Map, config: &mut Config) { .unwrap(), &PatternRegistry::construct(&config.great_spell_sigs), &mut config.entities, + &HashMap::new() ); contents.insert(Signature::from_sig(key), iota); } @@ -129,6 +130,7 @@ fn parse_entity(entity: &Map, config: &mut Config) { pair, &PatternRegistry::construct(&config.great_spell_sigs), &mut config.entities, + &HashMap::new() ) }); diff --git a/src/parser.rs b/src/parser.rs index 0e29eef..bae8cac 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -35,11 +35,14 @@ pub fn parse( let mut macros: Macros = HashMap::new(); let pairs = HexParser::parse(Rule::File, source)?; - for pair in pairs { + for pair in pairs.clone() { if Rule::Macro == pair.as_rule() { let hex_macro = parse_macro(pair, &pattern_registry, conf_entities); macros.insert(hex_macro.0, hex_macro.1); - } else if let Some(node) = construct_ast_node(pair, &pattern_registry, conf_entities) { + } + } + for pair in pairs { + if let Some(node) = construct_ast_node(pair, &pattern_registry, conf_entities, ¯os) { ast.push(node); } } @@ -54,8 +57,19 @@ fn parse_macro( ) -> (String, (PatternIota, AstNode)) { let mut inner = pair.into_inner(); let name = inner.next().unwrap().as_str().to_string(); - let pattern = parse_pattern(inner.next().unwrap(), pattern_registry, conf_entities); - let hex = construct_ast_node(inner.next().unwrap(), pattern_registry, conf_entities).unwrap(); + let pattern = parse_pattern( + inner.next().unwrap(), + pattern_registry, + conf_entities, + &HashMap::new(), + ); + let hex = construct_ast_node( + inner.next().unwrap(), + pattern_registry, + conf_entities, + &HashMap::new(), + ) + .unwrap(); (name, (pattern, hex)) } @@ -64,6 +78,7 @@ fn construct_ast_node( pair: Pair<'_, Rule>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> Option { match pair.as_rule() { Rule::Action => { @@ -78,6 +93,7 @@ fn construct_ast_node( righter, pattern_registry, conf_entities, + macros, )) } Rule::Op => { @@ -85,14 +101,21 @@ fn construct_ast_node( let name = pair.next().unwrap(); let arg = pair.next(); - Some(parse_op(name, arg, pattern_registry, conf_entities)) + Some(parse_op(name, arg, pattern_registry, conf_entities, macros)) } Rule::Var => Some(parse_var(pair)), - Rule::Embed => Some(parse_embed(pair, pattern_registry, conf_entities)), - Rule::IfBlock => Some(parse_if_block(pair, pattern_registry, conf_entities)), + Rule::Embed => Some(parse_embed(pair, pattern_registry, conf_entities, macros)), + Rule::IfBlock => Some(parse_if_block( + pair, + pattern_registry, + conf_entities, + macros, + )), Rule::Term => Some(AstNode::Hex( pair.into_inner() - .filter_map(|node| construct_ast_node(node, pattern_registry, conf_entities)) + .filter_map(|node| { + construct_ast_node(node, pattern_registry, conf_entities, macros) + }) .collect(), )), _ => None, @@ -104,6 +127,7 @@ fn parse_op( arg: Option>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> AstNode { AstNode::Op { name: { @@ -116,7 +140,9 @@ fn parse_op( }, arg: { arg.map(|pair| match pair.as_rule() { - Rule::Iota => OpValue::Iota(parse_iota(pair, pattern_registry, conf_entities)), + Rule::Iota => { + OpValue::Iota(parse_iota(pair, pattern_registry, conf_entities, macros)) + } Rule::Var => OpValue::Var(pair.as_str().to_string()), _ => unreachable!(), }) @@ -131,6 +157,7 @@ fn parse_action( righter: Option>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> AstNode { right .clone() @@ -141,6 +168,7 @@ fn parse_action( pair.clone(), pattern_registry, conf_entities, + macros, ))), line: pair.line_col(), }, @@ -153,8 +181,9 @@ fn parse_action( _ => AstNode::Action { name: format!("{}: {}", left.as_str(), right.unwrap().as_str()), - value: righter - .map(|p| ActionValue::Iota(parse_iota(p, pattern_registry, conf_entities))), + value: righter.map(|p| { + ActionValue::Iota(parse_iota(p, pattern_registry, conf_entities, macros)) + }), line: pair.line_col(), }, }) @@ -170,6 +199,7 @@ fn parse_action_iota( right: Option>, righter: Option>, pattern_registry: &PatternRegistry, + macros: &Macros, conf_entities: &mut HashMap, ) -> PatternIota { right @@ -182,13 +212,16 @@ fn parse_action_iota( pair.clone(), pattern_registry, conf_entities, + macros, ))), None, ), Rule::EntityType => PatternIota::from_name( pattern_registry, &format!("{}: {}", left.as_str(), right.unwrap().as_str()), - righter.map(|p| ActionValue::Iota(parse_iota(p, pattern_registry, conf_entities))), + righter.map(|p| { + ActionValue::Iota(parse_iota(p, pattern_registry, conf_entities, macros)) + }), None, ), Rule::BookkeeperValue => PatternIota::from_name( @@ -199,11 +232,15 @@ fn parse_action_iota( ), _ => unreachable!(), }) - .unwrap_or(PatternIota::from_name( - pattern_registry, - left.as_str(), - None, - None, + .unwrap_or(Ok( + //check if macro + macros + .get(left.as_str()) + .map(|(pattern, _)| pattern.clone()) + .unwrap_or_else( + //check if pattern name + || PatternIota::from_name(pattern_registry, left.as_str(), None, None).unwrap(), + ), )) .unwrap() } @@ -236,6 +273,7 @@ fn parse_embed( pair: Pair<'_, Rule>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> AstNode { let inner_pair = pair.clone().into_inner().next().unwrap(); AstNode::Op { @@ -251,7 +289,7 @@ fn parse_embed( arg: (inner_pair .into_inner() .next() - .map(|iota| OpValue::Iota(parse_iota(iota, pattern_registry, conf_entities)))), + .map(|iota| OpValue::Iota(parse_iota(iota, pattern_registry, conf_entities, macros)))), line: pair.line_col(), } } @@ -260,26 +298,38 @@ fn parse_if_block( pair: Pair<'_, Rule>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> AstNode { fn parse_inner( line: (usize, usize), mut inner: Pairs<'_, Rule>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> AstNode { AstNode::IfBlock { condition: { let mut condition = inner.next().unwrap().into_inner(); Box::new( - construct_ast_node(condition.next().unwrap(), pattern_registry, conf_entities) - .unwrap(), + construct_ast_node( + condition.next().unwrap(), + pattern_registry, + conf_entities, + macros, + ) + .unwrap(), ) }, succeed: { let mut succeed = inner.next().unwrap().into_inner(); Box::new( - construct_ast_node(succeed.next().unwrap(), pattern_registry, conf_entities) - .unwrap(), + construct_ast_node( + succeed.next().unwrap(), + pattern_registry, + conf_entities, + macros, + ) + .unwrap(), ) }, fail: { @@ -289,12 +339,17 @@ fn parse_if_block( branch.into_inner().next().unwrap(), pattern_registry, conf_entities, + macros, ) .unwrap(), ), - Rule::ElseIf => { - Box::new(parse_inner(line, inner, pattern_registry, conf_entities)) - } + Rule::ElseIf => Box::new(parse_inner( + line, + inner, + pattern_registry, + conf_entities, + macros, + )), _ => unreachable!(), }) }, @@ -306,6 +361,7 @@ fn parse_if_block( pair.into_inner(), pattern_registry, conf_entities, + macros, ) } @@ -313,11 +369,17 @@ pub fn parse_iota( pair: Pair<'_, Rule>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> Rc { let inner_pair = pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Number => Rc::new(inner_pair.as_str().parse::().unwrap()), - Rule::Pattern => Rc::new(parse_pattern(inner_pair, pattern_registry, conf_entities)), + Rule::Pattern => Rc::new(parse_pattern( + inner_pair.into_inner().next().unwrap(), + pattern_registry, + conf_entities, + macros, + )), Rule::Vector => { let mut inner = inner_pair.into_inner(); Rc::new(matrix![ @@ -346,7 +408,7 @@ pub fn parse_iota( let inner = inner_pair.into_inner(); Rc::new( inner - .map(|x| parse_iota(x, pattern_registry, conf_entities)) + .map(|x| parse_iota(x, pattern_registry, conf_entities, macros)) .collect::(), ) } @@ -375,33 +437,30 @@ fn parse_pattern( pair: Pair<'_, Rule>, pattern_registry: &PatternRegistry, conf_entities: &mut HashMap, + macros: &Macros, ) -> PatternIota { - match pair.clone().into_inner().next() { - Some(inner_pair) => match inner_pair.as_str() { - "{" => PatternIota::from_name(pattern_registry, "open_paren", None, None).unwrap(), - - "}" => PatternIota::from_name(pattern_registry, "close_paren", None, None).unwrap(), - - _ => match pair.as_rule() { - Rule::Action => { - let mut pairs = inner_pair.into_inner(); - parse_action_iota( - pairs.next().unwrap(), - pairs.next(), - pairs.next(), - pattern_registry, - conf_entities, - ) - } - Rule::PatternRaw => PatternIota::from_sig( - pair.into_inner().last().unwrap().as_str(), - None, - None, - ), - _ => unreachable!("{:?}", inner_pair.as_rule()), - }, + match pair.as_str() { + "{" => PatternIota::from_name(pattern_registry, "open_paren", None, None).unwrap(), + + "}" => PatternIota::from_name(pattern_registry, "close_paren", None, None).unwrap(), + + _ => match pair.as_rule() { + Rule::Action => { + let mut pairs = pair.into_inner(); + parse_action_iota( + pairs.next().unwrap(), + pairs.next(), + pairs.next(), + pattern_registry, + macros, + conf_entities, + ) + } + Rule::PatternRaw => { + PatternIota::from_sig(pair.into_inner().last().unwrap().as_str(), None, None) + } + _ => unreachable!("{:?}", pair.as_rule()), }, - None => unreachable!(), } }