From 88d5ac6ad7ed758223c4761be1126fb15efe1da5 Mon Sep 17 00:00:00 2001 From: Altareos Date: Fri, 3 Jun 2022 11:40:06 +0200 Subject: [PATCH] file manipulation basics --- sample/cp.pl.xml | 30 ++++++++++++++++ src/error.rs | 8 +++-- src/stl.rs | 91 +++++++++++++++++++++++++++++++++++++++++------- src/value.rs | 2 +- 4 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 sample/cp.pl.xml diff --git a/sample/cp.pl.xml b/sample/cp.pl.xml new file mode 100644 index 0000000..f941bb7 --- /dev/null +++ b/sample/cp.pl.xml @@ -0,0 +1,30 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/error.rs b/src/error.rs index b57f360..78e0293 100644 --- a/src/error.rs +++ b/src/error.rs @@ -24,11 +24,15 @@ impl fmt::Display for MissingAttribute { impl Error for MissingAttribute {} #[derive(Clone, Debug)] -pub struct BadArgumentCount(pub &'static str, pub usize); +pub struct BadArgumentCount(pub &'static str, pub usize, pub usize); impl fmt::Display for BadArgumentCount { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "bad argument count ({}) in call to '{}'", self.1, self.0) + write!( + f, + "bad argument count ({}, expected {}) in call to '{}'", + self.1, self.2, self.0 + ) } } diff --git a/src/stl.rs b/src/stl.rs index 96389e5..8396105 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -2,11 +2,13 @@ use super::error::{BadArgumentCount, InvalidArgument}; use super::{Context, Value}; use std::cell::RefCell; use std::error::Error; -use std::io; +use std::fs::{self, OpenOptions}; +use std::io::{stdin, stdout, Write}; use std::rc::Rc; pub fn inject_all(ctx: &mut Context) { ctx.assign(String::from("print"), Value::StdFunction(print)); + ctx.assign(String::from("print-line"), Value::StdFunction(print_line)); ctx.assign(String::from("input"), Value::StdFunction(input)); ctx.assign( String::from("string-split"), @@ -23,9 +25,26 @@ pub fn inject_all(ctx: &mut Context) { ctx.assign(String::from("to-ascii"), Value::StdFunction(to_ascii)); ctx.assign(String::from("from-ascii"), Value::StdFunction(from_ascii)); ctx.assign(String::from("get-args"), Value::StdFunction(get_args)); + ctx.assign(String::from("write-file"), Value::StdFunction(write_file)); + ctx.assign(String::from("read-file"), Value::StdFunction(read_file)); } fn print(vals: Vec) -> Result, Box> { + if vals.len() == 1 { + match &vals[0] { + Value::Integer(i) => print!("{}", i), + Value::Float(f) => print!("{}", f), + Value::String(s) => print!("{}", s), + v => print!("{:?}", v), // _ => Err("unprintable value")?, + }; + let _ = stdout().flush(); + Ok(Some(vals[0].clone())) + } else { + Err(BadArgumentCount("print", vals.len(), 1).into()) + } +} + +fn print_line(vals: Vec) -> Result, Box> { if vals.len() == 1 { match &vals[0] { Value::Integer(i) => println!("{}", i), @@ -33,20 +52,21 @@ fn print(vals: Vec) -> Result, Box> { Value::String(s) => println!("{}", s), v => println!("{:?}", v), // _ => Err("unprintable value")?, }; + let _ = stdout().flush(); Ok(Some(vals[0].clone())) } else { - Err(BadArgumentCount("print", vals.len()).into()) + Err(BadArgumentCount("print-line", vals.len(), 1).into()) } } fn input(vals: Vec) -> Result, Box> { if vals.len() == 0 { let mut line = String::new(); - io::stdin().read_line(&mut line)?; + stdin().read_line(&mut line)?; line.pop(); Ok(Some(Value::String(line))) } else { - Err(BadArgumentCount("input", vals.len()).into()) + Err(BadArgumentCount("input", vals.len(), 0).into()) } } @@ -68,7 +88,7 @@ fn string_split(vals: Vec) -> Result, Box> { Err(InvalidArgument("string-split", "target").into()) } } else { - Err(BadArgumentCount("string-split", vals.len()).into()) + Err(BadArgumentCount("string-split", vals.len(), 2).into()) } } @@ -90,7 +110,7 @@ fn array_set(vals: Vec) -> Result, Box> { Err(InvalidArgument("array-set", "array").into()) } } else { - Err(BadArgumentCount("array-set", vals.len()).into()) + Err(BadArgumentCount("array-set", vals.len(), 3).into()) } } @@ -103,7 +123,7 @@ fn array_push(vals: Vec) -> Result, Box> { Err(InvalidArgument("array-push", "array").into()) } } else { - Err(BadArgumentCount("array-push", vals.len()).into()) + Err(BadArgumentCount("array-push", vals.len(), 2).into()) } } @@ -119,7 +139,7 @@ fn array_pop(vals: Vec) -> Result, Box> { Err(InvalidArgument("array-pop", "array").into()) } } else { - Err(BadArgumentCount("array-pop", vals.len()).into()) + Err(BadArgumentCount("array-pop", vals.len(), 1).into()) } } @@ -140,7 +160,7 @@ fn array_get(vals: Vec) -> Result, Box> { Err(InvalidArgument("array-set", "array").into()) } } else { - Err(BadArgumentCount("array-get", vals.len()).into()) + Err(BadArgumentCount("array-get", vals.len(), 2).into()) } } @@ -152,7 +172,7 @@ fn array_length(vals: Vec) -> Result, Box> { Err(InvalidArgument("array-length", "array").into()) } } else { - Err(BadArgumentCount("array-length", vals.len()).into()) + Err(BadArgumentCount("array-length", vals.len(), 1).into()) } } @@ -168,7 +188,7 @@ fn to_ascii(vals: Vec) -> Result, Box> { Err(InvalidArgument("to-ascii", "integer").into()) } } else { - Err(BadArgumentCount("to-ascii", vals.len()).into()) + Err(BadArgumentCount("to-ascii", vals.len(), 1).into()) } } @@ -184,7 +204,7 @@ fn from_ascii(vals: Vec) -> Result, Box> { Err(InvalidArgument("from-ascii", "string").into()) } } else { - Err(BadArgumentCount("from-ascii", vals.len()).into()) + Err(BadArgumentCount("from-ascii", vals.len(), 1).into()) } } @@ -197,6 +217,51 @@ fn get_args(vals: Vec) -> Result, Box> { .collect(), ))))) } else { - Err(BadArgumentCount("get-args", vals.len()).into()) + Err(BadArgumentCount("get-args", vals.len(), 0).into()) + } +} + +fn write_file(vals: Vec) -> Result, Box> { + if vals.len() == 3 { + if let Value::String(path) = &vals[0] { + if let Value::String(contents) = &vals[1] { + if let Ok(mut file) = OpenOptions::new() + .write(true) + .create(true) + .append(Value::to_bool(&vals[2])) + .open(path) + { + if let Ok(_) = write!(file, "{}", contents) { + Ok(Some(Value::Integer(1))) + } else { + Ok(Some(Value::Integer(0))) + } + } else { + Ok(Some(Value::Integer(0))) + } + } else { + Err(InvalidArgument("write-file", "string").into()) + } + } else { + Err(InvalidArgument("write-file", "string").into()) + } + } else { + Err(BadArgumentCount("write-file", vals.len(), 3).into()) + } +} + +fn read_file(vals: Vec) -> Result, Box> { + if vals.len() == 1 { + if let Value::String(path) = &vals[0] { + if let Ok(contents) = fs::read_to_string(path) { + Ok(Some(Value::String(contents))) + } else { + Ok(None) + } + } else { + Err(InvalidArgument("read-file", "string").into()) + } + } else { + Err(BadArgumentCount("read-file", vals.len(), 1).into()) } } diff --git a/src/value.rs b/src/value.rs index 580e9a4..de6f563 100644 --- a/src/value.rs +++ b/src/value.rs @@ -19,7 +19,7 @@ impl Function { globals: &Context, ) -> Result, Box> { if args.len() != self.args.len() { - Err(BadArgumentCount("function", args.len()))? + Err(BadArgumentCount("function", args.len(), self.args.len()))? } self.args .iter()