Add support for loop breaks and function returns
This commit is contained in:
parent
c6b3155d52
commit
fbb5b72f24
207
src/engine.rs
207
src/engine.rs
@ -11,24 +11,28 @@ use std::ops::{Add, Sub, Mul, Div};
|
|||||||
use std::cmp::{Ord, Eq};
|
use std::cmp::{Ord, Eq};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EvalError {
|
pub enum EvalAltResult {
|
||||||
FunctionNotFound,
|
ErrorFunctionNotFound,
|
||||||
FunctionArgMismatch,
|
ErrorFunctionArgMismatch,
|
||||||
FunctionCallNotSupported,
|
ErrorFunctionCallNotSupported,
|
||||||
IfGuardMismatch,
|
ErrorIfGuardMismatch,
|
||||||
VariableNotFound,
|
ErrorVariableNotFound,
|
||||||
FunctionArityNotSupported
|
ErrorFunctionArityNotSupported,
|
||||||
|
LoopBreak,
|
||||||
|
Return(Box<Any>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for EvalError {
|
impl Error for EvalAltResult {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
EvalError::FunctionNotFound => "Function not found",
|
EvalAltResult::ErrorFunctionNotFound => "Function not found",
|
||||||
EvalError::FunctionArgMismatch => "Function argument types do not match",
|
EvalAltResult::ErrorFunctionArgMismatch => "Function argument types do not match",
|
||||||
EvalError::FunctionCallNotSupported => "Function call with > 2 argument not supported",
|
EvalAltResult::ErrorFunctionCallNotSupported => "Function call with > 2 argument not supported",
|
||||||
EvalError::IfGuardMismatch => "If guards expect boolean expression",
|
EvalAltResult::ErrorIfGuardMismatch => "If guards expect boolean expression",
|
||||||
EvalError::VariableNotFound => "Variable not found",
|
EvalAltResult::ErrorVariableNotFound => "Variable not found",
|
||||||
EvalError::FunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported"
|
EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported",
|
||||||
|
EvalAltResult::LoopBreak => "Loop broken before completion (not an error)",
|
||||||
|
EvalAltResult::Return(_) => "Function returned value (not an error)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,20 +41,20 @@ impl Error for EvalError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for EvalError {
|
impl fmt::Display for EvalAltResult {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.description())
|
write!(f, "{}", self.description())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FnType {
|
pub enum FnType {
|
||||||
ExternalFn0(Box<Fn()->Result<Box<Any>, EvalError>>),
|
ExternalFn0(Box<Fn()->Result<Box<Any>, EvalAltResult>>),
|
||||||
ExternalFn1(Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalError>>),
|
ExternalFn1(Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>>),
|
||||||
ExternalFn2(Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
|
ExternalFn2(Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>>),
|
||||||
ExternalFn3(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
|
ExternalFn3(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>>),
|
||||||
ExternalFn4(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
|
ExternalFn4(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>>),
|
||||||
ExternalFn5(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
|
ExternalFn5(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>>),
|
||||||
ExternalFn6(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
|
ExternalFn6(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>>),
|
||||||
|
|
||||||
InternalFn(FnDef)
|
InternalFn(FnDef)
|
||||||
}
|
}
|
||||||
@ -63,7 +67,7 @@ pub type Scope = Vec<(String, Box<Any>)>;
|
|||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
fn call_fn(&self, name: &str, arg1: Option<&mut Box<Any>>, arg2: Option<&mut Box<Any>>, arg3: Option<&mut Box<Any>>,
|
fn call_fn(&self, name: &str, arg1: Option<&mut Box<Any>>, arg2: Option<&mut Box<Any>>, arg3: Option<&mut Box<Any>>,
|
||||||
arg4: Option<&mut Box<Any>>, arg5: Option<&mut Box<Any>>, arg6: Option<&mut Box<Any>>) -> Result<Box<Any>, EvalError> {
|
arg4: Option<&mut Box<Any>>, arg5: Option<&mut Box<Any>>, arg6: Option<&mut Box<Any>>) -> Result<Box<Any>, EvalAltResult> {
|
||||||
|
|
||||||
match self.fns.get(name) {
|
match self.fns.get(name) {
|
||||||
Some(ref vf) => {
|
Some(ref vf) => {
|
||||||
@ -78,6 +82,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 6 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
||||||
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
||||||
@ -95,14 +101,17 @@ impl Engine {
|
|||||||
new_scope.push((f.params[4].clone(), r5));
|
new_scope.push((f.params[4].clone(), r5));
|
||||||
new_scope.push((f.params[5].clone(), r6));
|
new_scope.push((f.params[5].clone(), r6));
|
||||||
},
|
},
|
||||||
_ => return Err(EvalError::FunctionArgMismatch)
|
_ => return Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
|
}
|
||||||
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
}
|
}
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), Some(ref mut a5), None) => {
|
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), Some(ref mut a5), None) => {
|
||||||
for arr_f in *vf {
|
for arr_f in *vf {
|
||||||
@ -114,6 +123,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 5 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
||||||
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
||||||
@ -129,14 +140,17 @@ impl Engine {
|
|||||||
new_scope.push((f.params[3].clone(), r4));
|
new_scope.push((f.params[3].clone(), r4));
|
||||||
new_scope.push((f.params[4].clone(), r5));
|
new_scope.push((f.params[4].clone(), r5));
|
||||||
},
|
},
|
||||||
_ => return Err(EvalError::FunctionArgMismatch)
|
_ => return Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
|
}
|
||||||
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
}
|
}
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), None, None) => {
|
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), None, None) => {
|
||||||
for arr_f in *vf {
|
for arr_f in *vf {
|
||||||
@ -148,6 +162,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 4 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
||||||
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
||||||
@ -160,14 +176,17 @@ impl Engine {
|
|||||||
new_scope.push((f.params[2].clone(), r3));
|
new_scope.push((f.params[2].clone(), r3));
|
||||||
new_scope.push((f.params[3].clone(), r4));
|
new_scope.push((f.params[3].clone(), r4));
|
||||||
},
|
},
|
||||||
_ => return Err(EvalError::FunctionArgMismatch)
|
_ => return Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
|
}
|
||||||
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
}
|
}
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), None, None, None) => {
|
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), None, None, None) => {
|
||||||
for arr_f in *vf {
|
for arr_f in *vf {
|
||||||
@ -179,6 +198,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 3 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
||||||
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
||||||
@ -189,14 +210,17 @@ impl Engine {
|
|||||||
new_scope.push((f.params[1].clone(), r2));
|
new_scope.push((f.params[1].clone(), r2));
|
||||||
new_scope.push((f.params[2].clone(), r3));
|
new_scope.push((f.params[2].clone(), r3));
|
||||||
},
|
},
|
||||||
_ => return Err(EvalError::FunctionArgMismatch)
|
_ => return Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
|
}
|
||||||
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
}
|
}
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
(Some(ref mut a1), Some(ref mut a2), None, None, None, None) => {
|
(Some(ref mut a1), Some(ref mut a2), None, None, None, None) => {
|
||||||
for arr_f in *vf {
|
for arr_f in *vf {
|
||||||
@ -208,6 +232,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 2 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
||||||
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
|
||||||
@ -216,14 +242,17 @@ impl Engine {
|
|||||||
new_scope.push((f.params[0].clone(), r1));
|
new_scope.push((f.params[0].clone(), r1));
|
||||||
new_scope.push((f.params[1].clone(), r2));
|
new_scope.push((f.params[1].clone(), r2));
|
||||||
},
|
},
|
||||||
_ => return Err(EvalError::FunctionArgMismatch)
|
_ => return Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
|
}
|
||||||
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
}
|
}
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
(Some(ref mut a1), None, None, None, None, None) => {
|
(Some(ref mut a1), None, None, None, None, None) => {
|
||||||
for arr_f in *vf {
|
for arr_f in *vf {
|
||||||
@ -235,20 +264,25 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 1 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
|
||||||
match result1 {
|
match result1 {
|
||||||
Ok(r1) => {
|
Ok(r1) => {
|
||||||
new_scope.push((f.params[0].clone(), r1));
|
new_scope.push((f.params[0].clone(), r1));
|
||||||
},
|
},
|
||||||
_ => return Err(EvalError::FunctionArgMismatch)
|
_ => return Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
|
}
|
||||||
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
}
|
}
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
for arr_f in *vf {
|
for arr_f in *vf {
|
||||||
@ -260,17 +294,22 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& FnType::InternalFn(ref f) => {
|
& FnType::InternalFn(ref f) => {
|
||||||
|
if f.params.len() != 0 { return Err(EvalAltResult::ErrorFunctionArgMismatch); }
|
||||||
|
|
||||||
let mut new_scope: Scope = Vec::new();
|
let mut new_scope: Scope = Vec::new();
|
||||||
return self.eval_stmt(&mut new_scope, &*f.body);
|
match self.eval_stmt(&mut new_scope, &*f.body) {
|
||||||
|
Err(EvalAltResult::Return(x)) => return Ok(x),
|
||||||
|
x => return x
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EvalError::FunctionArgMismatch);
|
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Err(EvalError::FunctionNotFound)
|
None => Err(EvalAltResult::ErrorFunctionNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +319,7 @@ impl Engine {
|
|||||||
&(clone_helper as fn(T)->T).register(self, "clone");
|
&(clone_helper as fn(T)->T).register(self, "clone");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result<Box<Any>, EvalError> {
|
fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result<Box<Any>, EvalAltResult> {
|
||||||
match *expr {
|
match *expr {
|
||||||
Expr::IntConst(i) => Ok(Box::new(i)),
|
Expr::IntConst(i) => Ok(Box::new(i)),
|
||||||
Expr::StringConst(ref s) => Ok(Box::new(s.clone())),
|
Expr::StringConst(ref s) => Ok(Box::new(s.clone())),
|
||||||
@ -290,7 +329,7 @@ impl Engine {
|
|||||||
return self.call_fn("clone", Some(val), None, None, None, None, None);
|
return self.call_fn("clone", Some(val), None, None, None, None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
Expr::Assignment(ref id, ref rhs) => {
|
Expr::Assignment(ref id, ref rhs) => {
|
||||||
match **id {
|
match **id {
|
||||||
@ -304,9 +343,9 @@ impl Engine {
|
|||||||
return Ok(Box::new(()));
|
return Ok(Box::new(()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
_ => Err(EvalError::VariableNotFound)
|
_ => Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::FnCall(ref fn_name, ref args) => {
|
Expr::FnCall(ref fn_name, ref args) => {
|
||||||
@ -361,7 +400,7 @@ impl Engine {
|
|||||||
Some(&mut arg5), Some(&mut arg6))
|
Some(&mut arg5), Some(&mut arg6))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Err(EvalError::FunctionCallNotSupported)
|
Err(EvalAltResult::ErrorFunctionCallNotSupported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::MethodCall(ref target, ref fn_name, ref args) => {
|
Expr::MethodCall(ref target, ref fn_name, ref args) => {
|
||||||
@ -371,7 +410,7 @@ impl Engine {
|
|||||||
return self.call_fn(&fn_name, Some(val), None, None, None, None, None);
|
return self.call_fn(&fn_name, Some(val), None, None, None, None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
else if args.len() == 1 {
|
else if args.len() == 1 {
|
||||||
let mut arg = try!(self.eval_expr(scope, &args[0]));
|
let mut arg = try!(self.eval_expr(scope, &args[0]));
|
||||||
@ -381,7 +420,7 @@ impl Engine {
|
|||||||
return self.call_fn(&fn_name, Some(val), Some(&mut arg), None, None, None, None);
|
return self.call_fn(&fn_name, Some(val), Some(&mut arg), None, None, None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
else if args.len() == 2 {
|
else if args.len() == 2 {
|
||||||
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
||||||
@ -392,7 +431,7 @@ impl Engine {
|
|||||||
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), None, None, None);
|
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), None, None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
else if args.len() == 3 {
|
else if args.len() == 3 {
|
||||||
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
||||||
@ -404,7 +443,7 @@ impl Engine {
|
|||||||
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), None, None);
|
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
else if args.len() == 4 {
|
else if args.len() == 4 {
|
||||||
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
||||||
@ -418,7 +457,7 @@ impl Engine {
|
|||||||
Some(&mut arg4), None);
|
Some(&mut arg4), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
else if args.len() == 5 {
|
else if args.len() == 5 {
|
||||||
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
|
||||||
@ -433,10 +472,10 @@ impl Engine {
|
|||||||
Some(&mut arg4), Some(&mut arg5));
|
Some(&mut arg4), Some(&mut arg5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EvalError::VariableNotFound)
|
Err(EvalAltResult::ErrorVariableNotFound)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Err(EvalError::FunctionCallNotSupported)
|
Err(EvalAltResult::ErrorFunctionCallNotSupported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::True => {
|
Expr::True => {
|
||||||
@ -448,17 +487,21 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result<Box<Any>, EvalError> {
|
fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result<Box<Any>, EvalAltResult> {
|
||||||
match *stmt {
|
match *stmt {
|
||||||
Stmt::Expr(ref e) => {
|
Stmt::Expr(ref e) => {
|
||||||
self.eval_expr(scope, e)
|
self.eval_expr(scope, e)
|
||||||
}
|
}
|
||||||
Stmt::Block(ref b) => {
|
Stmt::Block(ref b) => {
|
||||||
let prev_len = scope.len();
|
let prev_len = scope.len();
|
||||||
let mut last_result : Result<Box<Any>, EvalError> = Ok(Box::new(0));
|
let mut last_result : Result<Box<Any>, EvalAltResult> = Ok(Box::new(()));
|
||||||
|
|
||||||
for s in b.iter() {
|
for s in b.iter() {
|
||||||
last_result = self.eval_stmt(scope, s)
|
last_result = self.eval_stmt(scope, s);
|
||||||
|
match last_result {
|
||||||
|
Err(x) => {last_result = Err(x); break},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while scope.len() > prev_len {
|
while scope.len() > prev_len {
|
||||||
@ -478,7 +521,7 @@ impl Engine {
|
|||||||
Ok(Box::new(()))
|
Ok(Box::new(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => Err(EvalError::IfGuardMismatch)
|
Err(_) => Err(EvalAltResult::ErrorIfGuardMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::IfElse(ref guard, ref body, ref else_body) => {
|
Stmt::IfElse(ref guard, ref body, ref else_body) => {
|
||||||
@ -492,7 +535,7 @@ impl Engine {
|
|||||||
self.eval_stmt(scope, else_body)
|
self.eval_stmt(scope, else_body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => Err(EvalError::IfGuardMismatch)
|
Err(_) => Err(EvalAltResult::ErrorIfGuardMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::While(ref guard, ref body) => {
|
Stmt::While(ref guard, ref body) => {
|
||||||
@ -501,16 +544,26 @@ impl Engine {
|
|||||||
match guard_result.downcast::<bool>() {
|
match guard_result.downcast::<bool>() {
|
||||||
Ok(g) => {
|
Ok(g) => {
|
||||||
if *g {
|
if *g {
|
||||||
try!(self.eval_stmt(scope, body));
|
match self.eval_stmt(scope, body) {
|
||||||
|
Err(EvalAltResult::LoopBreak) => { return Ok(Box::new(())); }
|
||||||
|
Err(x) => { return Err(x); }
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Ok(Box::new(()));
|
return Ok(Box::new(()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => return Err(EvalError::IfGuardMismatch)
|
Err(_) => return Err(EvalAltResult::ErrorIfGuardMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Stmt::Break => return Err(EvalAltResult::LoopBreak),
|
||||||
|
Stmt::Return => return Err(EvalAltResult::Return(Box::new(()))),
|
||||||
|
Stmt::ReturnWithVal(ref a) => {
|
||||||
|
let result = try!(self.eval_expr(scope, a));
|
||||||
|
return Err(EvalAltResult::Return(result));
|
||||||
|
}
|
||||||
Stmt::Var(ref name, ref init) => {
|
Stmt::Var(ref name, ref init) => {
|
||||||
match init {
|
match init {
|
||||||
& Some(ref v) => {
|
& Some(ref v) => {
|
||||||
@ -526,13 +579,13 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval(&mut self, input: String) -> Result<Box<Any>, EvalError> {
|
pub fn eval(&mut self, input: String) -> Result<Box<Any>, EvalAltResult> {
|
||||||
let mut scope: Scope = Vec::new();
|
let mut scope: Scope = Vec::new();
|
||||||
|
|
||||||
self.eval_with_scope(&mut scope, input)
|
self.eval_with_scope(&mut scope, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_with_scope(&mut self, scope: &mut Scope, input: String) -> Result<Box<Any>, EvalError> {
|
pub fn eval_with_scope(&mut self, scope: &mut Scope, input: String) -> Result<Box<Any>, EvalAltResult> {
|
||||||
let tokens = lex(&input);
|
let tokens = lex(&input);
|
||||||
|
|
||||||
let mut peekables = tokens.peekable();
|
let mut peekables = tokens.peekable();
|
||||||
@ -540,11 +593,11 @@ impl Engine {
|
|||||||
|
|
||||||
match tree {
|
match tree {
|
||||||
Ok((ref os, ref fns)) => {
|
Ok((ref os, ref fns)) => {
|
||||||
let mut x: Result<Box<Any>, EvalError> = Ok(Box::new(()));
|
let mut x: Result<Box<Any>, EvalAltResult> = Ok(Box::new(()));
|
||||||
|
|
||||||
for f in fns {
|
for f in fns {
|
||||||
if f.params.len() > 6 {
|
if f.params.len() > 6 {
|
||||||
return Err(EvalError::FunctionArityNotSupported);
|
return Err(EvalAltResult::ErrorFunctionArityNotSupported);
|
||||||
}
|
}
|
||||||
let name = f.name.clone();
|
let name = f.name.clone();
|
||||||
let local_f = f.clone();
|
let local_f = f.clone();
|
||||||
@ -557,7 +610,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
Err(_) => Err(EvalError::FunctionArgMismatch)
|
Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,7 +769,18 @@ fn test_if() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
fn test_while() {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
if let Ok(result) = engine.eval("var x = 0; while x < 10 { x = x + 1; if x > 5 { break } } x".to_string()).unwrap().downcast::<i32>() {
|
||||||
|
assert_eq!(*result, 6);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
fn test_var_scope() {
|
fn test_var_scope() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
let mut scope: Scope = Vec::new();
|
let mut scope: Scope = Vec::new();
|
||||||
@ -792,6 +856,13 @@ fn test_internal_fn() {
|
|||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Ok(result) = engine.eval("fn bob() { return 4; 5 } bob()".to_string()).unwrap().downcast::<i32>() {
|
||||||
|
assert_eq!(*result, 4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
|
||||||
use engine::{EvalError, Engine, FnType};
|
use engine::{EvalAltResult, Engine, FnType};
|
||||||
|
|
||||||
pub trait FnRegister {
|
pub trait FnRegister {
|
||||||
fn register(self, engine: &mut Engine, name: &str);
|
fn register(self, engine: &mut Engine, name: &str);
|
||||||
@ -10,7 +10,7 @@ pub trait FnRegister {
|
|||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone, Z: Any+Clone> FnRegister for fn(&mut T, U, V, W, X, Y)->Z {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone, Z: Any+Clone> FnRegister for fn(&mut T, U, V, W, X, Y)->Z {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>,
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>,
|
||||||
&mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
|
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
||||||
@ -26,7 +26,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
match (inside1, inside2, inside3, inside4, inside5, inside6) {
|
match (inside1, inside2, inside3, inside4, inside5, inside6) {
|
||||||
(Some(b), Some(c), Some(d), Some(e), Some(f), Some(g)) => Ok(Box::new(self(b, c.clone(), d.clone(),
|
(Some(b), Some(c), Some(d), Some(e), Some(f), Some(g)) => Ok(Box::new(self(b, c.clone(), d.clone(),
|
||||||
e.clone(), f.clone(), g.clone())) as Box<Any>),
|
e.clone(), f.clone(), g.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -39,7 +39,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone, Z: Any+Clone> FnRegister for fn(T, U, V, W, X, Y)->Z {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone, Z: Any+Clone> FnRegister for fn(T, U, V, W, X, Y)->Z {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>,
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>,
|
||||||
&mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
|
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
||||||
@ -55,7 +55,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
match (inside1, inside2, inside3, inside4, inside5, inside6) {
|
match (inside1, inside2, inside3, inside4, inside5, inside6) {
|
||||||
(Some(b), Some(c), Some(d), Some(e), Some(f), Some(g)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(),
|
(Some(b), Some(c), Some(d), Some(e), Some(f), Some(g)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(),
|
||||||
e.clone(), f.clone(), g.clone())) as Box<Any>),
|
e.clone(), f.clone(), g.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -67,7 +67,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone> FnRegister for fn(&mut T, U, V, W, X)->Y {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone> FnRegister for fn(&mut T, U, V, W, X)->Y {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
||||||
arg5: &mut Box<Any>| {
|
arg5: &mut Box<Any>| {
|
||||||
@ -81,7 +81,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
match (inside1, inside2, inside3, inside4, inside5) {
|
match (inside1, inside2, inside3, inside4, inside5) {
|
||||||
(Some(b), Some(c), Some(d), Some(e), Some(f)) => Ok(Box::new(self(b, c.clone(), d.clone(),
|
(Some(b), Some(c), Some(d), Some(e), Some(f)) => Ok(Box::new(self(b, c.clone(), d.clone(),
|
||||||
e.clone(), f.clone())) as Box<Any>),
|
e.clone(), f.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -93,7 +93,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone> FnRegister for fn(T, U, V, W, X)->Y {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: Any+Clone> FnRegister for fn(T, U, V, W, X)->Y {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>,
|
||||||
arg5: &mut Box<Any>| {
|
arg5: &mut Box<Any>| {
|
||||||
@ -107,7 +107,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
match (inside1, inside2, inside3, inside4, inside5) {
|
match (inside1, inside2, inside3, inside4, inside5) {
|
||||||
(Some(b), Some(c), Some(d), Some(e), Some(f)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(),
|
(Some(b), Some(c), Some(d), Some(e), Some(f)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(),
|
||||||
e.clone(), f.clone())) as Box<Any>),
|
e.clone(), f.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -119,7 +119,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnRegister for fn(&mut T, U, V, W)->X {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnRegister for fn(&mut T, U, V, W)->X {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>| {
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>| {
|
||||||
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
||||||
@ -129,7 +129,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnReg
|
|||||||
|
|
||||||
match (inside1, inside2, inside3, inside4) {
|
match (inside1, inside2, inside3, inside4) {
|
||||||
(Some(b), Some(c), Some(d), Some(e)) => Ok(Box::new(self(b, c.clone(), d.clone(), e.clone())) as Box<Any>),
|
(Some(b), Some(c), Some(d), Some(e)) => Ok(Box::new(self(b, c.clone(), d.clone(), e.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -141,7 +141,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnReg
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnRegister for fn(T, U, V, W)->X {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnRegister for fn(T, U, V, W)->X {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>| {
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>| {
|
||||||
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
||||||
@ -151,7 +151,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnReg
|
|||||||
|
|
||||||
match (inside1, inside2, inside3, inside4) {
|
match (inside1, inside2, inside3, inside4) {
|
||||||
(Some(b), Some(c), Some(d), Some(e)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(), e.clone())) as Box<Any>),
|
(Some(b), Some(c), Some(d), Some(e)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(), e.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -163,7 +163,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnReg
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(&mut T, U, V)->W {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(&mut T, U, V)->W {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>| {
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>| {
|
||||||
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
||||||
@ -172,7 +172,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(&
|
|||||||
|
|
||||||
match (inside1, inside2, inside3) {
|
match (inside1, inside2, inside3) {
|
||||||
(Some(b), Some(c), Some(d)) => Ok(Box::new(self(b, c.clone(), d.clone())) as Box<Any>),
|
(Some(b), Some(c), Some(d)) => Ok(Box::new(self(b, c.clone(), d.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -184,7 +184,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(&
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(T, U, V)->W {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(T, U, V)->W {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>| {
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>| {
|
||||||
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
||||||
@ -193,7 +193,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(T
|
|||||||
|
|
||||||
match (inside1, inside2, inside3) {
|
match (inside1, inside2, inside3) {
|
||||||
(Some(b), Some(c), Some(d)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone())) as Box<Any>),
|
(Some(b), Some(c), Some(d)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -205,7 +205,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(T
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(&mut T, U)->V {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(&mut T, U)->V {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>| {
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>| {
|
||||||
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
||||||
@ -213,7 +213,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(&mut T, U)->V {
|
|||||||
|
|
||||||
match (inside1, inside2) {
|
match (inside1, inside2) {
|
||||||
(Some(b), Some(c)) => Ok(Box::new(self(b, c.clone())) as Box<Any>),
|
(Some(b), Some(c)) => Ok(Box::new(self(b, c.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -225,7 +225,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(&mut T, U)->V {
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(T, U)->V {
|
impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(T, U)->V {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>| {
|
move |arg1: &mut Box<Any>, arg2: &mut Box<Any>| {
|
||||||
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
let inside1 = (*arg1).downcast_mut() as Option<&mut T>;
|
||||||
@ -233,7 +233,7 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(T, U)->V {
|
|||||||
|
|
||||||
match (inside1, inside2) {
|
match (inside1, inside2) {
|
||||||
(Some(b), Some(c)) => Ok(Box::new(self(b.clone(), c.clone())) as Box<Any>),
|
(Some(b), Some(c)) => Ok(Box::new(self(b.clone(), c.clone())) as Box<Any>),
|
||||||
_ => Err(EvalError::FunctionArgMismatch)
|
_ => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -245,14 +245,14 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(T, U)->V {
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(&mut T)->U {
|
impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(&mut T)->U {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg: &mut Box<Any>| {
|
move |arg: &mut Box<Any>| {
|
||||||
let inside = (*arg).downcast_mut() as Option<&mut T>;
|
let inside = (*arg).downcast_mut() as Option<&mut T>;
|
||||||
|
|
||||||
match inside {
|
match inside {
|
||||||
Some(b) => Ok(Box::new(self(b)) as Box<Any>),
|
Some(b) => Ok(Box::new(self(b)) as Box<Any>),
|
||||||
None => Err(EvalError::FunctionArgMismatch)
|
None => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -264,13 +264,13 @@ impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(&mut T)->U {
|
|||||||
|
|
||||||
impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(T)->U {
|
impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(T)->U {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move |arg: &mut Box<Any>| {
|
move |arg: &mut Box<Any>| {
|
||||||
let inside = (*arg).downcast_mut() as Option<&mut T>;
|
let inside = (*arg).downcast_mut() as Option<&mut T>;
|
||||||
match inside {
|
match inside {
|
||||||
Some(b) => Ok(Box::new(self(b.clone())) as Box<Any>),
|
Some(b) => Ok(Box::new(self(b.clone())) as Box<Any>),
|
||||||
None => Err(EvalError::FunctionArgMismatch)
|
None => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -282,7 +282,7 @@ impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(T)->U {
|
|||||||
|
|
||||||
impl<T: Any+Clone> FnRegister for fn()->T {
|
impl<T: Any+Clone> FnRegister for fn()->T {
|
||||||
fn register(self, engine: &mut Engine, name: &str) {
|
fn register(self, engine: &mut Engine, name: &str) {
|
||||||
let wrapped : Box<Fn()->Result<Box<Any>, EvalError>> =
|
let wrapped : Box<Fn()->Result<Box<Any>, EvalAltResult>> =
|
||||||
Box::new(
|
Box::new(
|
||||||
move || { Ok(Box::new(self()) as Box<Any>) }
|
move || { Ok(Box::new(self()) as Box<Any>) }
|
||||||
);
|
);
|
||||||
|
@ -18,7 +18,6 @@ mod parser;
|
|||||||
// * How it works
|
// * How it works
|
||||||
// * Vectors
|
// * Vectors
|
||||||
// * Return
|
// * Return
|
||||||
// * Break
|
|
||||||
// * Tighten parser?
|
// * Tighten parser?
|
||||||
// * Errors with positions?
|
// * Errors with positions?
|
||||||
// * Remove empty box values?
|
// * Remove empty box values?
|
||||||
|
@ -85,7 +85,7 @@ pub struct FnDef {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Stmt { If(Box<Expr>, Box<Stmt>), IfElse(Box<Expr>, Box<Stmt>, Box<Stmt>), While(Box<Expr>, Box<Stmt>),
|
pub enum Stmt { If(Box<Expr>, Box<Stmt>), IfElse(Box<Expr>, Box<Stmt>, Box<Stmt>), While(Box<Expr>, Box<Stmt>),
|
||||||
Var(String, Option<Box<Expr>>), Block(Box<Vec<Stmt>>), Expr(Box<Expr>) }
|
Var(String, Option<Box<Expr>>), Block(Box<Vec<Stmt>>), Expr(Box<Expr>), Break, Return, ReturnWithVal(Box<Expr>) }
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(String, Box<Vec<Expr>>),
|
pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(String, Box<Vec<Expr>>),
|
||||||
@ -95,7 +95,7 @@ pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(S
|
|||||||
pub enum Token { IntConst(i32), Identifier(String), StringConst(String), LCurly, RCurly, LParen, RParen, LSquare, RSquare,
|
pub enum Token { IntConst(i32), Identifier(String), StringConst(String), LCurly, RCurly, LParen, RParen, LSquare, RSquare,
|
||||||
Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, Else, While,
|
Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, Else, While,
|
||||||
LessThan, GreaterThan, Bang, LessThanEqual, GreaterThanEqual, EqualTo, NotEqualTo, Pipe, Or, Ampersand, And, Fn,
|
LessThan, GreaterThan, Bang, LessThanEqual, GreaterThanEqual, EqualTo, NotEqualTo, Pipe, Or, Ampersand, And, Fn,
|
||||||
LexErr(LexError) }
|
Break, Return, LexErr(LexError) }
|
||||||
|
|
||||||
pub struct TokenIterator<'a> {
|
pub struct TokenIterator<'a> {
|
||||||
char_stream: Peekable<Chars<'a>>
|
char_stream: Peekable<Chars<'a>>
|
||||||
@ -157,6 +157,12 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
else if out == "while" {
|
else if out == "while" {
|
||||||
return Some(Token::While);
|
return Some(Token::While);
|
||||||
}
|
}
|
||||||
|
else if out == "break" {
|
||||||
|
return Some(Token::Break);
|
||||||
|
}
|
||||||
|
else if out == "return" {
|
||||||
|
return Some(Token::Return);
|
||||||
|
}
|
||||||
else if out == "fn" {
|
else if out == "fn" {
|
||||||
return Some(Token::Fn);
|
return Some(Token::Fn);
|
||||||
}
|
}
|
||||||
@ -569,6 +575,14 @@ fn parse_stmt<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, Parse
|
|||||||
match input.peek() {
|
match input.peek() {
|
||||||
Some(& Token::If) => parse_if(input),
|
Some(& Token::If) => parse_if(input),
|
||||||
Some(& Token::While) => parse_while(input),
|
Some(& Token::While) => parse_while(input),
|
||||||
|
Some(& Token::Break) => {input.next(); Ok(Stmt::Break)},
|
||||||
|
Some(& Token::Return) => {
|
||||||
|
input.next();
|
||||||
|
match input.peek() {
|
||||||
|
Some(& Token::Semicolon) => Ok(Stmt::Return),
|
||||||
|
_ => {let ret = try!(parse_expr(input)); Ok(Stmt::ReturnWithVal(Box::new(ret))) }
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(& Token::LCurly) => parse_block(input),
|
Some(& Token::LCurly) => parse_block(input),
|
||||||
Some(& Token::Var) => parse_var(input),
|
Some(& Token::Var) => parse_var(input),
|
||||||
_ => parse_expr_stmt(input)
|
_ => parse_expr_stmt(input)
|
||||||
|
Loading…
Reference in New Issue
Block a user