file manipulation basics
This commit is contained in:
30
sample/cp.pl.xml
Normal file
30
sample/cp.pl.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<program name="files">
|
||||
<main>
|
||||
<assign variable="args">
|
||||
<call function="get-args">
|
||||
<arguments />
|
||||
</call>
|
||||
</assign>
|
||||
<call function="write-file">
|
||||
<arguments>
|
||||
<call function="array-get">
|
||||
<arguments>
|
||||
<value variable="args" />
|
||||
<integer value="2" />
|
||||
</arguments>
|
||||
</call>
|
||||
<call function="read-file">
|
||||
<arguments>
|
||||
<call function="array-get">
|
||||
<arguments>
|
||||
<value variable="args" />
|
||||
<integer value="1" />
|
||||
</arguments>
|
||||
</call>
|
||||
</arguments>
|
||||
</call>
|
||||
<integer value="0" />
|
||||
</arguments>
|
||||
</call>
|
||||
</main>
|
||||
</program>
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
91
src/stl.rs
91
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
if vals.len() == 1 {
|
||||
match &vals[0] {
|
||||
Value::Integer(i) => println!("{}", i),
|
||||
@@ -33,20 +52,21 @@ fn print(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
.collect(),
|
||||
)))))
|
||||
} else {
|
||||
Err(BadArgumentCount("get-args", vals.len()).into())
|
||||
Err(BadArgumentCount("get-args", vals.len(), 0).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_file(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ impl Function {
|
||||
globals: &Context,
|
||||
) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
if args.len() != self.args.len() {
|
||||
Err(BadArgumentCount("function", args.len()))?
|
||||
Err(BadArgumentCount("function", args.len(), self.args.len()))?
|
||||
}
|
||||
self.args
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user