From 2735a391b888951ee1a9a06e1ae5a7bc42b12480 Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Mon, 29 May 2023 18:06:44 -0700 Subject: [PATCH] Implement basic variable assignment --- Cargo.lock | 70 +++++++++++++++++++++++++++++++++++ demo/demo.rpy | 6 +++ renrs/Cargo.toml | 1 + renrs/src/lib.rs | 13 ++++--- renrs/src/parser/block.rs | 74 ++++++++++++++++++++++++++++++++----- renrs/src/parser/command.rs | 40 +++++++------------- renrs/src/parser/event.rs | 5 ++- renrs/src/parser/mod.rs | 3 +- 8 files changed, 167 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8fae11a..344da23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,21 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.8.3" @@ -50,6 +65,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -96,6 +126,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "debug-cell" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ee4fc02f25a0400fb57135bcdde6d58a3025718749375f2f97abc3deb3a4ef" +dependencies = [ + "backtrace", +] + [[package]] name = "digest" version = "0.10.7" @@ -199,6 +238,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + [[package]] name = "glu-sys" version = "0.1.4" @@ -286,6 +331,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -301,6 +355,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.2" @@ -431,6 +494,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" name = "renrs" version = "0.1.0" dependencies = [ + "debug-cell", "pest", "pest_derive", "regex", @@ -453,6 +517,12 @@ dependencies = [ "sfml", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustix" version = "0.37.19" diff --git a/demo/demo.rpy b/demo/demo.rpy index 2334443..59e0d74 100644 --- a/demo/demo.rpy +++ b/demo/demo.rpy @@ -1,4 +1,10 @@ # Control testing +$ x = "3" +"Bob will be here in [x] seconds." +$ x = "2" +"Bob will be here in [x] seconds." +$ x = "1" +"Bob will be here in [x] seconds." "Bob" "I will not say anything, [foo]" define foo = "bar" if False: diff --git a/renrs/Cargo.toml b/renrs/Cargo.toml index 2515810..9036169 100644 --- a/renrs/Cargo.toml +++ b/renrs/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +debug-cell = "0.1.1" pest = "2.6.0" pest_derive = "2.6.0" regex = "1.8.3" diff --git a/renrs/src/lib.rs b/renrs/src/lib.rs index 7e8193a..df4fabd 100644 --- a/renrs/src/lib.rs +++ b/renrs/src/lib.rs @@ -1,8 +1,9 @@ -use std::{cell::RefCell, path::PathBuf, rc::Rc}; +use debug_cell::RefCell; +use std::path::PathBuf; +use std::rc::Rc; pub mod parser; -use parser::block::CommandBlock; -use parser::command::Command; +use parser::block::{CommandBlock, CommandContext}; use parser::event::Event; use parser::parse_file; @@ -19,7 +20,7 @@ impl State { pub fn next(&mut self) -> Option { while let Some(command) = self.next_command() { - let event = command.execute(&self.script); + let event = command.execute(); if event.as_ref().map_or(false, |event| event.is_blocking()) { return event; } @@ -27,7 +28,7 @@ impl State { None } - fn next_command(&mut self) -> Option { - self.script.borrow_mut().next() + fn next_command(&mut self) -> Option { + self.script.borrow_mut().next(&self.script) } } diff --git a/renrs/src/parser/block.rs b/renrs/src/parser/block.rs index e1f770f..9d8527e 100644 --- a/renrs/src/parser/block.rs +++ b/renrs/src/parser/block.rs @@ -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>>, control: Option, elements: Vec, next: Option, - variables: Option>>>, + pub variables: Option>>>, +} + +pub struct CommandContext { + pub context: Rc>, + pub command: Command, +} + +impl CommandContext { + pub fn execute(&self) -> Option { + 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 { + pub fn next<'a>(&mut self, self_rc: &Rc>) -> Option { 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>) -> Rc> { + 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>), diff --git a/renrs/src/parser/command.rs b/renrs/src/parser/command.rs index 69a020b..b4a5b21 100644 --- a/renrs/src/parser/command.rs +++ b/renrs/src/parser/command.rs @@ -1,8 +1,4 @@ -use std::{cell::RefCell, rc::Rc}; - use super::{ - block::CommandBlock, - event::Event, token::Token, utils::{describe_line, parse_line}, Pair, @@ -14,23 +10,7 @@ pub enum Command { Say { name: Option, text: String }, Eat { food: String, politely: bool }, Define { variable: String, value: Token }, -} - -impl Command { - pub fn execute(&self, context: &Rc>) -> Option { - use Command::*; - Some( - match self { - Say { name, text } => Event::Say { - name: name.clone(), - text: text.clone(), - }, - Define { .. } => panic!("define command should not be executed at runtime!"), - Eat { .. } => return None, - } - .process(context), - ) - } + Assign { variable: String, value: Token }, } pub fn parse_command(pair: Pair) -> Command { @@ -45,20 +25,28 @@ pub fn parse_command(pair: Pair) -> Command { match line.as_slice() { [Str(text)] => Say { name: None, - text: text.to_owned(), + text: text.clone(), }, [Str(name), Str(text)] => Say { - name: Some(name.to_owned()), - text: text.to_owned(), + name: Some(name.clone()), + text: text.clone(), }, [Keyword(keyword), Keyword(variable), Keyword(equals), value] if keyword.eq("define") && equals.eq("=") => { Define { - variable: variable.to_owned(), + variable: variable.clone(), value: value.clone(), } - } + }, + [Keyword(keyword), Keyword(variable), Keyword(equals), value] + if keyword.eq("$") && equals.eq("=") => + { + Assign { + variable: variable.clone(), + value: value.clone(), + } + }, [Keyword(keyword), Str(food), tail @ ..] if keyword.eq("eat") => Eat { food: food.to_owned(), politely: match tail { diff --git a/renrs/src/parser/event.rs b/renrs/src/parser/event.rs index 8bdcced..fe0a402 100644 --- a/renrs/src/parser/event.rs +++ b/renrs/src/parser/event.rs @@ -1,4 +1,5 @@ -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{collections::HashMap, rc::Rc}; +use debug_cell::RefCell; use regex::Regex; @@ -27,7 +28,7 @@ impl Event { .as_deref() .map(|name| interpolate_string(&name, &variables)); *text = interpolate_string(&text, &variables); - } + }, } self } diff --git a/renrs/src/parser/mod.rs b/renrs/src/parser/mod.rs index e446c75..9cd77d2 100644 --- a/renrs/src/parser/mod.rs +++ b/renrs/src/parser/mod.rs @@ -7,7 +7,8 @@ mod utils; pub type Pair<'a> = pest::iterators::Pair<'a, Rule>; -use std::{cell::RefCell, fs, path::PathBuf, rc::Rc}; +use std::{fs, path::PathBuf, rc::Rc}; +use debug_cell::RefCell; pub use pest::Parser; use pest_derive::Parser;