|
|
|
@ -1,23 +1,67 @@
|
|
|
|
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
|
|
|
|
use std::{collections::HashMap, rc::Rc};
|
|
|
|
|
use debug_cell::RefCell;
|
|
|
|
|
|
|
|
|
|
use super::{
|
|
|
|
|
command::{parse_command, Command},
|
|
|
|
|
control::{parse_control, Control},
|
|
|
|
|
token::Token,
|
|
|
|
|
Pair, Rule,
|
|
|
|
|
Pair, Rule, event::Event,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct CommandBlock {
|
|
|
|
|
parent: Option<Rc<RefCell<CommandBlock>>>,
|
|
|
|
|
control: Option<Control>,
|
|
|
|
|
elements: Vec<BlockElement>,
|
|
|
|
|
next: Option<usize>,
|
|
|
|
|
variables: Option<Rc<RefCell<HashMap<String, Token>>>>,
|
|
|
|
|
pub variables: Option<Rc<RefCell<HashMap<String, Token>>>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct CommandContext {
|
|
|
|
|
pub context: Rc<RefCell<CommandBlock>>,
|
|
|
|
|
pub command: Command,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CommandContext {
|
|
|
|
|
pub fn execute(&self) -> Option<Event> {
|
|
|
|
|
use Command::*;
|
|
|
|
|
Some(
|
|
|
|
|
match &self.command {
|
|
|
|
|
Say { name, text } => Event::Say {
|
|
|
|
|
name: name.clone(),
|
|
|
|
|
text: text.clone(),
|
|
|
|
|
},
|
|
|
|
|
Define { .. } => panic!("define command should not be executed at runtime!"),
|
|
|
|
|
Assign { variable, value } => {
|
|
|
|
|
if let Token::Keyword(_) = value {
|
|
|
|
|
todo!("assignment variable interpolation isn't implemented");
|
|
|
|
|
}
|
|
|
|
|
let root = self.context
|
|
|
|
|
.borrow()
|
|
|
|
|
.get_root(&self.context);
|
|
|
|
|
// Don't want to re-borrow if root is self
|
|
|
|
|
let root = if Rc::ptr_eq(&self.context, &root) {
|
|
|
|
|
&self.context
|
|
|
|
|
} else {
|
|
|
|
|
&root
|
|
|
|
|
};
|
|
|
|
|
root
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.variables
|
|
|
|
|
.as_ref()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.insert(variable.clone(), value.clone());
|
|
|
|
|
return None;
|
|
|
|
|
},
|
|
|
|
|
Eat { .. } => return None,
|
|
|
|
|
}
|
|
|
|
|
.process(&self.context),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CommandBlock {
|
|
|
|
|
pub fn next(&mut self) -> Option<Command> {
|
|
|
|
|
pub fn next<'a>(&mut self, self_rc: &Rc<RefCell<Self>>) -> Option<CommandContext> {
|
|
|
|
|
let mut next = match self.next {
|
|
|
|
|
Some(next) => next,
|
|
|
|
|
None => return None,
|
|
|
|
@ -30,13 +74,16 @@ impl CommandBlock {
|
|
|
|
|
for element in &mut self.elements[next..] {
|
|
|
|
|
match element {
|
|
|
|
|
BlockElement::Command(command) => {
|
|
|
|
|
result = Some(command.clone());
|
|
|
|
|
result = Some(CommandContext {
|
|
|
|
|
context: self_rc.clone(),
|
|
|
|
|
command: command.clone(),
|
|
|
|
|
});
|
|
|
|
|
next += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
BlockElement::Block(block) => match block.borrow_mut().next() {
|
|
|
|
|
Some(command) => {
|
|
|
|
|
result = Some(command.clone());
|
|
|
|
|
BlockElement::Block(block) => match block.borrow_mut().next(&block) {
|
|
|
|
|
Some(context_command) => {
|
|
|
|
|
result = Some(context_command);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
@ -71,6 +118,14 @@ impl CommandBlock {
|
|
|
|
|
None => HashMap::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_root(&self, self_rc: &Rc<RefCell<Self>>) -> Rc<RefCell<Self>> {
|
|
|
|
|
if let Some(parent) = &self.parent {
|
|
|
|
|
parent.borrow().get_root(&parent)
|
|
|
|
|
} else {
|
|
|
|
|
self_rc.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for CommandBlock {
|
|
|
|
@ -85,7 +140,6 @@ impl Default for CommandBlock {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
enum BlockElement {
|
|
|
|
|
Command(Command),
|
|
|
|
|
Block(Rc<RefCell<CommandBlock>>),
|
|
|
|
|