Add support for arrays
This commit is contained in:
parent
ceadc0977f
commit
b1ccaf4516
4
scripts/array.rhai
Normal file
4
scripts/array.rhai
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
var x = [1, 2, 3];
|
||||||
|
print(x[1]);
|
||||||
|
x[1] = 5;
|
||||||
|
print(x[1]);
|
@ -15,6 +15,7 @@ pub enum EvalAltResult {
|
|||||||
ErrorFunctionNotFound,
|
ErrorFunctionNotFound,
|
||||||
ErrorFunctionArgMismatch,
|
ErrorFunctionArgMismatch,
|
||||||
ErrorFunctionCallNotSupported,
|
ErrorFunctionCallNotSupported,
|
||||||
|
ErrorIndexMismatch,
|
||||||
ErrorIfGuardMismatch,
|
ErrorIfGuardMismatch,
|
||||||
ErrorVariableNotFound(String),
|
ErrorVariableNotFound(String),
|
||||||
ErrorFunctionArityNotSupported,
|
ErrorFunctionArityNotSupported,
|
||||||
@ -26,12 +27,14 @@ pub enum EvalAltResult {
|
|||||||
Return(Box<Any>)
|
Return(Box<Any>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Error for EvalAltResult {
|
impl Error for EvalAltResult {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
EvalAltResult::ErrorFunctionNotFound => "Function not found",
|
EvalAltResult::ErrorFunctionNotFound => "Function not found",
|
||||||
EvalAltResult::ErrorFunctionArgMismatch => "Function argument types do not match",
|
EvalAltResult::ErrorFunctionArgMismatch => "Function argument types do not match",
|
||||||
EvalAltResult::ErrorFunctionCallNotSupported => "Function call with > 2 argument not supported",
|
EvalAltResult::ErrorFunctionCallNotSupported => "Function call with > 2 argument not supported",
|
||||||
|
EvalAltResult::ErrorIndexMismatch => "Index does not match array",
|
||||||
EvalAltResult::ErrorIfGuardMismatch => "If guards expect boolean expression",
|
EvalAltResult::ErrorIfGuardMismatch => "If guards expect boolean expression",
|
||||||
EvalAltResult::ErrorVariableNotFound(_) => "Variable not found",
|
EvalAltResult::ErrorVariableNotFound(_) => "Variable not found",
|
||||||
EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported",
|
EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported",
|
||||||
@ -537,10 +540,32 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
Err(EvalAltResult::ErrorVariableNotFound(id.clone()))
|
Err(EvalAltResult::ErrorVariableNotFound(id.clone()))
|
||||||
}
|
}
|
||||||
|
Expr::Index(ref id, ref idx_raw) => {
|
||||||
|
let idx = try!(self.eval_expr(scope, idx_raw));
|
||||||
|
|
||||||
|
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
|
||||||
|
if *id == *name {
|
||||||
|
if let Ok(i) = idx.downcast::<i32>() {
|
||||||
|
if let Some(arr_typed) = (*val).downcast_mut() as Option<&mut Vec<Box<Any>>> {
|
||||||
|
return self.call_fn("clone", Some(&mut arr_typed[*i as usize]), None, None, None, None, None);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(EvalAltResult::ErrorIndexMismatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(EvalAltResult::ErrorIndexMismatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(EvalAltResult::ErrorVariableNotFound(id.clone()))
|
||||||
|
}
|
||||||
Expr::Assignment(ref id, ref rhs) => {
|
Expr::Assignment(ref id, ref rhs) => {
|
||||||
|
let rhs_val = try!(self.eval_expr(scope, rhs));
|
||||||
|
|
||||||
match **id {
|
match **id {
|
||||||
Expr::Identifier(ref n) => {
|
Expr::Identifier(ref n) => {
|
||||||
let rhs_val = try!(self.eval_expr(scope, rhs));
|
|
||||||
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
|
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
|
||||||
if *n == *name {
|
if *n == *name {
|
||||||
|
|
||||||
@ -551,9 +576,29 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
Err(EvalAltResult::ErrorVariableNotFound(n.clone()))
|
Err(EvalAltResult::ErrorVariableNotFound(n.clone()))
|
||||||
}
|
}
|
||||||
Expr::Dot(ref dot_lhs, ref dot_rhs) => {
|
Expr::Index(ref id, ref idx_raw) => {
|
||||||
let rhs_val = try!(self.eval_expr(scope, rhs));
|
let idx = try!(self.eval_expr(scope, idx_raw));
|
||||||
|
|
||||||
|
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
|
||||||
|
if *id == *name {
|
||||||
|
if let Ok(i) = idx.downcast::<i32>() {
|
||||||
|
if let Some(arr_typed) = (*val).downcast_mut() as Option<&mut Vec<Box<Any>>> {
|
||||||
|
arr_typed[*i as usize] = rhs_val;
|
||||||
|
return Ok(Box::new(()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(EvalAltResult::ErrorIndexMismatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(EvalAltResult::ErrorIndexMismatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(EvalAltResult::ErrorVariableNotFound(id.clone()))
|
||||||
|
}
|
||||||
|
Expr::Dot(ref dot_lhs, ref dot_rhs) => {
|
||||||
self.set_dot_val(scope, dot_lhs, dot_rhs, rhs_val)
|
self.set_dot_val(scope, dot_lhs, dot_rhs, rhs_val)
|
||||||
}
|
}
|
||||||
_ => Err(EvalAltResult::ErrorAssignmentToUnknownLHS)
|
_ => Err(EvalAltResult::ErrorAssignmentToUnknownLHS)
|
||||||
@ -562,6 +607,16 @@ impl Engine {
|
|||||||
Expr::Dot(ref lhs, ref rhs) => {
|
Expr::Dot(ref lhs, ref rhs) => {
|
||||||
self.get_dot_val(scope, lhs, rhs)
|
self.get_dot_val(scope, lhs, rhs)
|
||||||
}
|
}
|
||||||
|
Expr::Array(ref contents) => {
|
||||||
|
let mut arr = Vec::new();
|
||||||
|
|
||||||
|
for item in (*contents).iter() {
|
||||||
|
let arg = try!(self.eval_expr(scope, item));
|
||||||
|
arr.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Box::new(arr))
|
||||||
|
}
|
||||||
Expr::FnCall(ref fn_name, ref args) => {
|
Expr::FnCall(ref fn_name, ref args) => {
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
self.call_fn(&fn_name, None, None, None, None, None, None)
|
self.call_fn(&fn_name, None, None, None, None, None, None)
|
||||||
@ -838,6 +893,12 @@ impl Engine {
|
|||||||
|
|
||||||
reg_op!(engine, "||", or, bool);
|
reg_op!(engine, "||", or, bool);
|
||||||
reg_op!(engine, "&&", and, bool);
|
reg_op!(engine, "&&", and, bool);
|
||||||
|
|
||||||
|
//engine.register_fn("[]", idx);
|
||||||
|
//FIXME? Registering array lookups are a special case because we want to return boxes directly
|
||||||
|
//let ent = engine.fns.entry("[]".to_string()).or_insert(Vec::new());
|
||||||
|
//(*ent).push(FnType::ExternalFn2(Box::new(idx)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Engine {
|
pub fn new() -> Engine {
|
||||||
@ -1170,3 +1231,24 @@ fn test_string() {
|
|||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec() {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
if let Ok(result) = engine.eval::<i32>("var x = [1, 2, 3]; x[1]") {
|
||||||
|
assert_eq!(result, 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(result) = engine.eval::<i32>("var y = [1, 2, 3]; y[1] = 5; y[1]") {
|
||||||
|
assert_eq!(result, 5);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ pub trait FnRegister<A, RetVal, Args> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W, X, Y, Z> FnRegister<A, Z, (&'a mut T, U, V, W, X, Y)> for Engine
|
impl<'a, A, T, U, V, W, X, Y, Z> FnRegister<A, Z, (&'a mut T, U, V, W, X, Y)> for Engine
|
||||||
where A: 'static+Fn(&mut T, U, V, W, X, Y) -> Z, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any,
|
where A: 'static+Fn(&mut T, U, V, W, X, Y) -> Z, T: Any, U: Clone+Any, V: Clone+Any, W: Clone+Any,
|
||||||
X: Clone+Any, Y: Clone+Any, Z: Clone+Any
|
X: Clone+Any, Y: Clone+Any, Z: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
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>,
|
||||||
@ -41,7 +41,7 @@ impl<'a, A, T, U, V, W, X, Y, Z> FnRegister<A, Z, (&'a mut T, U, V, W, X, Y)> fo
|
|||||||
|
|
||||||
impl<'a, A, T, U, V, W, X, Y, Z> FnRegister<A, Z, (&'a T, U, V, W, X, Y)> for Engine
|
impl<'a, A, T, U, V, W, X, Y, Z> FnRegister<A, Z, (&'a T, U, V, W, X, Y)> for Engine
|
||||||
where A: 'static+Fn(T, U, V, W, X, Y) -> Z, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any,
|
where A: 'static+Fn(T, U, V, W, X, Y) -> Z, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any,
|
||||||
X: Clone+Any, Y: Clone+Any, Z: Clone+Any
|
X: Clone+Any, Y: Clone+Any, Z: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
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>,
|
||||||
@ -72,7 +72,7 @@ impl<'a, A, T, U, V, W, X, Y, Z> FnRegister<A, Z, (&'a T, U, V, W, X, Y)> for En
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W, X, Y> FnRegister<A, Y, (&'a mut T, U, V, W, X)> for Engine
|
impl<'a, A, T, U, V, W, X, Y> FnRegister<A, Y, (&'a mut T, U, V, W, X)> for Engine
|
||||||
where A: 'static+Fn(&mut T, U, V, W, X) -> Y, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Clone+Any, Y: Clone+Any
|
where A: 'static+Fn(&mut T, U, V, W, X) -> Y, T: Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Clone+Any, Y: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -100,7 +100,7 @@ impl<'a, A, T, U, V, W, X, Y> FnRegister<A, Y, (&'a mut T, U, V, W, X)> for Engi
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W, X, Y> FnRegister<A, Y, (&'a T, U, V, W, X)> for Engine
|
impl<'a, A, T, U, V, W, X, Y> FnRegister<A, Y, (&'a T, U, V, W, X)> for Engine
|
||||||
where A: 'static+Fn(T, U, V, W, X) -> Y, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Clone+Any, Y: Clone+Any
|
where A: 'static+Fn(T, U, V, W, X) -> Y, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Clone+Any, Y: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -128,7 +128,7 @@ impl<'a, A, T, U, V, W, X, Y> FnRegister<A, Y, (&'a T, U, V, W, X)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W, X> FnRegister<A, X, (&'a mut T, U, V, W)> for Engine
|
impl<'a, A, T, U, V, W, X> FnRegister<A, X, (&'a mut T, U, V, W)> for Engine
|
||||||
where A: 'static+Fn(&mut T, U, V, W) -> X, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Clone+Any
|
where A: 'static+Fn(&mut T, U, V, W) -> X, T: Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -152,7 +152,7 @@ impl<'a, A, T, U, V, W, X> FnRegister<A, X, (&'a mut T, U, V, W)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W, X> FnRegister<A, X, (&'a T, U, V, W)> for Engine
|
impl<'a, A, T, U, V, W, X> FnRegister<A, X, (&'a T, U, V, W)> for Engine
|
||||||
where A: 'static+Fn(T, U, V, W) -> X, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Clone+Any
|
where A: 'static+Fn(T, U, V, W) -> X, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any, X: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -176,7 +176,7 @@ impl<'a, A, T, U, V, W, X> FnRegister<A, X, (&'a T, U, V, W)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W> FnRegister<A, W, (&'a mut T, U, V)> for Engine
|
impl<'a, A, T, U, V, W> FnRegister<A, W, (&'a mut T, U, V)> for Engine
|
||||||
where A: 'static+Fn(&mut T, U, V) -> W, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any
|
where A: 'static+Fn(&mut T, U, V) -> W, T: Any, U: Clone+Any, V: Clone+Any, W: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -199,7 +199,7 @@ impl<'a, A, T, U, V, W> FnRegister<A, W, (&'a mut T, U, V)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V, W> FnRegister<A, W, (&'a T, U, V)> for Engine
|
impl<'a, A, T, U, V, W> FnRegister<A, W, (&'a T, U, V)> for Engine
|
||||||
where A: 'static+Fn(T, U, V) -> W, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Clone+Any
|
where A: 'static+Fn(T, U, V) -> W, T: Clone+Any, U: Clone+Any, V: Clone+Any, W: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -222,7 +222,7 @@ impl<'a, A, T, U, V, W> FnRegister<A, W, (&'a T, U, V)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V> FnRegister<A, V, (&'a mut T, U)> for Engine
|
impl<'a, A, T, U, V> FnRegister<A, V, (&'a mut T, U)> for Engine
|
||||||
where A: 'static+Fn(&mut T, U) -> V, T: Clone+Any, U: Clone+Any, V: Clone+Any
|
where A: 'static+Fn(&mut T, U) -> V, T: Any, U: Clone+Any, V: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -244,7 +244,7 @@ impl<'a, A, T, U, V> FnRegister<A, V, (&'a mut T, U)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U, V> FnRegister<A, V, (&'a T, U)> for Engine
|
impl<'a, A, T, U, V> FnRegister<A, V, (&'a T, U)> for Engine
|
||||||
where A: 'static+Fn(T, U) -> V, T: Clone+Any, U: Clone+Any, V: Clone+Any
|
where A: 'static+Fn(T, U) -> V, T: Clone+Any, U: Clone+Any, V: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -266,7 +266,7 @@ impl<'a, A, T, U, V> FnRegister<A, V, (&'a T, U)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, T, U> FnRegister<A, U, (&'a mut T)> for Engine
|
impl<'a, A, T, U> FnRegister<A, U, (&'a mut T)> for Engine
|
||||||
where A: 'static+Fn(&mut T) -> U, T: Clone+Any, U: Clone+Any
|
where A: 'static+Fn(&mut T) -> U, T: Any, U: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -288,7 +288,7 @@ impl<'a, A, T, U> FnRegister<A, U, (&'a mut T)> for Engine
|
|||||||
|
|
||||||
|
|
||||||
impl<'a, A, T, U> FnRegister<A, U, (&'a T)> for Engine
|
impl<'a, A, T, U> FnRegister<A, U, (&'a T)> for Engine
|
||||||
where A: 'static+Fn(T) -> U, T: Clone+Any, U: Clone+Any
|
where A: 'static+Fn(T) -> U, T: Clone+Any, U: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalAltResult>> =
|
||||||
@ -308,7 +308,7 @@ impl<'a, A, T, U> FnRegister<A, U, (&'a T)> for Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<A, T> FnRegister<A, T, ()> for Engine
|
impl<A, T> FnRegister<A, T, ()> for Engine
|
||||||
where A: 'static+Fn() -> T, T: Clone+Any
|
where A: 'static+Fn() -> T, T: Any
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, fun: A) {
|
fn register_fn(&mut self, name: &str, fun: A) {
|
||||||
let wrapped : Box<Fn()->Result<Box<Any>, EvalAltResult>> =
|
let wrapped : Box<Fn()->Result<Box<Any>, EvalAltResult>> =
|
||||||
|
@ -41,7 +41,9 @@ pub enum ParseError {
|
|||||||
MissingRParen,
|
MissingRParen,
|
||||||
MissingLCurly,
|
MissingLCurly,
|
||||||
MissingRCurly,
|
MissingRCurly,
|
||||||
|
MissingRSquare,
|
||||||
MalformedCallExpr,
|
MalformedCallExpr,
|
||||||
|
MalformedIndexExpr,
|
||||||
VarExpectsIdentifier,
|
VarExpectsIdentifier,
|
||||||
FnMissingName,
|
FnMissingName,
|
||||||
FnMissingParams
|
FnMissingParams
|
||||||
@ -56,7 +58,9 @@ impl Error for ParseError {
|
|||||||
ParseError::MissingRParen => "Expected ')'",
|
ParseError::MissingRParen => "Expected ')'",
|
||||||
ParseError::MissingLCurly => "Expected '{'",
|
ParseError::MissingLCurly => "Expected '{'",
|
||||||
ParseError::MissingRCurly => "Expected '}'",
|
ParseError::MissingRCurly => "Expected '}'",
|
||||||
|
ParseError::MissingRSquare => "Expected ']'",
|
||||||
ParseError::MalformedCallExpr => "Call contains bad expression",
|
ParseError::MalformedCallExpr => "Call contains bad expression",
|
||||||
|
ParseError::MalformedIndexExpr => "Indexing expression missing correct index",
|
||||||
ParseError::VarExpectsIdentifier => "'var' expects the name of a variable",
|
ParseError::VarExpectsIdentifier => "'var' expects the name of a variable",
|
||||||
ParseError::FnMissingName => "Function declaration is missing name",
|
ParseError::FnMissingName => "Function declaration is missing name",
|
||||||
ParseError::FnMissingParams => "Function declaration is missing parameters"
|
ParseError::FnMissingParams => "Function declaration is missing parameters"
|
||||||
@ -87,7 +91,7 @@ pub enum Stmt { If(Box<Expr>, Box<Stmt>), IfElse(Box<Expr>, Box<Stmt>, Box<Stmt>
|
|||||||
|
|
||||||
#[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>>),
|
||||||
Assignment(Box<Expr>, Box<Expr>), Dot(Box<Expr>, Box<Expr>), True, False }
|
Assignment(Box<Expr>, Box<Expr>), Dot(Box<Expr>, Box<Expr>), Index(String, Box<Expr>), Array(Box<Vec<Expr>>), True, False }
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
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,
|
||||||
@ -355,12 +359,7 @@ fn parse_paren_expr<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ident_expr<'a>(id: String, input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
fn parse_call_expr<'a>(id: String, input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
||||||
match input.peek() {
|
|
||||||
Some(&Token::LParen) => {input.next();},
|
|
||||||
_ => return Ok(Expr::Identifier(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
|
|
||||||
match input.peek() {
|
match input.peek() {
|
||||||
@ -392,6 +391,59 @@ fn parse_ident_expr<'a>(id: String, input: &mut Peekable<TokenIterator<'a>>) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_index_expr<'a>(id: String, input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
||||||
|
if let Ok(idx) = parse_expr(input) {
|
||||||
|
match input.peek() {
|
||||||
|
Some(&Token::RSquare) => {
|
||||||
|
input.next();
|
||||||
|
return Ok(Expr::Index(id, Box::new(idx)))
|
||||||
|
},
|
||||||
|
_ => return Err(ParseError::MalformedIndexExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(ParseError::MalformedIndexExpr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ident_expr<'a>(id: String, input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
||||||
|
match input.peek() {
|
||||||
|
Some(&Token::LParen) => {input.next(); parse_call_expr(id, input)},
|
||||||
|
Some(&Token::LSquare) => {input.next(); parse_index_expr(id, input)},
|
||||||
|
_ => return Ok(Expr::Identifier(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_array_expr<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
||||||
|
let mut arr = Vec::new();
|
||||||
|
|
||||||
|
let skip_contents = match input.peek() {
|
||||||
|
Some(& Token::RSquare) => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
if !skip_contents {
|
||||||
|
while let Some(_) = input.peek() {
|
||||||
|
arr.push(try!(parse_expr(input)));
|
||||||
|
match input.peek() {
|
||||||
|
Some(& Token::Comma) => {input.next();},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
match input.peek() {
|
||||||
|
Some(& Token::RSquare) => break,
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match input.peek() {
|
||||||
|
Some(& Token::RSquare) => {input.next(); Ok(Expr::Array(Box::new(arr)))},
|
||||||
|
_ => Err(ParseError::MissingRSquare)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_primary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
fn parse_primary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, ParseError> {
|
||||||
if let Some(token) = input.next() {
|
if let Some(token) = input.next() {
|
||||||
match token {
|
match token {
|
||||||
@ -399,6 +451,7 @@ fn parse_primary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, Pa
|
|||||||
Token::StringConst(ref s) => {Ok(Expr::StringConst(s.clone()))},
|
Token::StringConst(ref s) => {Ok(Expr::StringConst(s.clone()))},
|
||||||
Token::Identifier(ref s) => {parse_ident_expr(s.clone(), input)},
|
Token::Identifier(ref s) => {parse_ident_expr(s.clone(), input)},
|
||||||
Token::LParen => {parse_paren_expr(input)},
|
Token::LParen => {parse_paren_expr(input)},
|
||||||
|
Token::LSquare => {parse_array_expr(input)},
|
||||||
Token::True => {Ok(Expr::True)},
|
Token::True => {Ok(Expr::True)},
|
||||||
Token::False => {Ok(Expr::False)},
|
Token::False => {Ok(Expr::False)},
|
||||||
Token::LexErr(le) => {println!("Error: {}", le); Err(ParseError::BadInput)}
|
Token::LexErr(le) => {println!("Error: {}", le); Err(ParseError::BadInput)}
|
||||||
|
Loading…
Reference in New Issue
Block a user