use sixu::error::RuntimeError;
use sixu::format::*;
use sixu::parser::parse;
use sixu::runtime::{Runtime, RuntimeContext, RuntimeExecutor, StepResult};
const SAMPLE: &str = r#"
::entry {
first line1
@tttt foo=2
@tttt2(foo=4, bar=8)
{
@tttt foo=16
#replace paragraph="abc"
}
@tttt foo=100
}
::abc {
@tttt foo=32
{
@tttt foo=64
#call paragraph="def"
}
@tttt foo=128
#finish
}
::def {
@tttt foo=256
## 512 ##
}
"#;
#[test]
fn main() {
let mut sample = Sample::new();
sample.init();
loop {
match sample.runtime.step() {
Ok(StepResult::Done) => {
}
Ok(StepResult::NeedsCondition(_)) => {
sample.runtime.resume_condition(true);
}
Ok(StepResult::NeedsScript(script)) => {
let force_parse_int = script.trim().parse::<u32>().unwrap();
assert_eq!(force_parse_int, 512, "script should be 512");
println!("force_parse_int: {}", force_parse_int);
sample.runtime.executor_mut().last_value += force_parse_int;
sample.runtime.resume_script(None, false);
}
Ok(StepResult::NeedsStoryFile(_)) => {
unreachable!("story file loading not used in this test")
}
Err(RuntimeError::StoryFinished) => {
println!("Story finished");
break;
}
Err(RuntimeError::StoryNotStarted) => {
println!("Story not started - this might indicate completion");
break;
}
Err(err) => {
println!("Error: {:?}", err);
break;
}
}
}
}
struct SampleExecutor {
last_value: u32,
}
impl SampleExecutor {
pub fn new() -> Self {
Self { last_value: 0 }
}
}
impl RuntimeExecutor for SampleExecutor {
fn handle_command(
&mut self,
_ctx: &mut RuntimeContext,
command_line: &ResolvedCommandLine,
) -> sixu::error::Result<bool> {
if command_line.command == "tttt" {
let foo = command_line.get_argument("foo").unwrap();
assert!(foo.is_integer(), "foo should be an integer");
assert!(foo.as_integer().is_ok(), "foo should be an integer");
println!("foo: {}", foo.as_integer().unwrap());
self.last_value += *foo.as_integer().unwrap() as u32;
}
if command_line.command == "tttt2" {
let foo = command_line.get_argument("foo").unwrap();
assert!(foo.is_integer(), "foo should be an integer");
assert!(foo.as_integer().is_ok(), "foo should be an integer");
let bar = command_line.get_argument("bar").unwrap();
assert!(bar.is_integer(), "bar should be an integer");
assert!(bar.as_integer().is_ok(), "bar should be an integer");
println!(
"foo: {}, bar: {}",
foo.as_integer().unwrap(),
bar.as_integer().unwrap()
);
self.last_value += *foo.as_integer().unwrap() as u32;
self.last_value += *bar.as_integer().unwrap() as u32;
}
Ok(false)
}
fn handle_extra_system_call(
&mut self,
_ctx: &mut RuntimeContext,
_systemcall_line: &ResolvedSystemCallLine,
) -> sixu::error::Result<bool> {
unreachable!()
}
fn handle_text(
&mut self,
_ctx: &mut RuntimeContext,
_leading: Option<&str>,
text: Option<&str>,
_tailing: Option<&str>,
) -> sixu::error::Result<bool> {
if let Some(text) = text {
let last_char = text.chars().last().unwrap_or('0');
let last_char_as_int = last_char.to_digit(10).unwrap_or(0);
assert_ne!(last_char_as_int, 0, "last char should be a digit");
println!("text value: {}", last_char_as_int);
self.last_value += last_char_as_int;
}
Ok(false)
}
fn finished(&mut self, _ctx: &mut RuntimeContext) {
println!("Finished execution");
assert_eq!(self.last_value, 1023, "last value should be 1023");
}
}
struct Sample {
runtime: Runtime<SampleExecutor>,
}
impl Sample {
pub fn new() -> Self {
Self {
runtime: Runtime::new_with_context(SampleExecutor::new(), RuntimeContext::new()),
}
}
pub fn init(&mut self) {
let (_, story) = parse("test", SAMPLE).unwrap();
self.runtime.context_mut().stories_mut().push(story);
self.runtime.start("test", Some("entry")).unwrap();
}
}