Browse Source

Change addition and multiplication to take any number of arguments

master
Colin Reeder 1 year ago
parent
commit
9125f520f0
2 changed files with 58 additions and 58 deletions
  1. +2
    -2
      README.md
  2. +56
    -56
      src/eval.rs

+ 2
- 2
README.md View File

@@ -23,8 +23,8 @@ Four supports the following data types:
ID | Operation | Description
---- | --------------------- | -----------
0 | function declaration | Takes one expression as a parameter, and returns a callable function form of it. Functions can be used as operations.
1 | multiply | Takes two values and multiplies them. If either is nil, returns the other. Strings can be multiplied by integers for repetition.
4 | add | Adds two numbers, or concatenates two strings. If either value is nil, returns the other.
1 | multiply | Takes any number of values and multiplies them, ignoring nils. If passed zero values, returns nil. Strings can be multiplied by integers for repetition.
4 | add | Takes any number of values and adds or concatenates them, ignoring nils. If passed zero values, returns nil.
8 | divide | Divides two numbers. If either value is nil, returns nil.
9 | character from string | Takes a string and an integer, returns the character at the given index in the given string as a string.
12 | conditional | Takes three values. If the first value is 4, the second is returned, otherwise the third is returned.


+ 56
- 56
src/eval.rs View File

@@ -49,69 +49,69 @@ fn exec_op(pos: Location, id: i32, args: &[ParsedExpr], ctx: &Context) -> Result
}
1 => {
// multiply
if args.len() != 2 {
return Err(EvalError::InvalidParameters(
pos,
format!(
"multiply operation requires exactly 2 parameters, got {}",
args.len()
),
));
}

let a = eval(&args[0], ctx)?;
let b = eval(&args[1], ctx)?;

Ok(match (a, b) {
(Value::Nil, b) => b,
(a, Value::Nil) => a,
(Value::I32(a), Value::I32(b)) => Value::I32(a * b),
(Value::String(a), Value::I32(b)) | (Value::I32(b), Value::String(a)) => {
Value::String(a.repeat(b.max(0) as usize))
}
(Value::String(_), Value::String(_)) => {
return Err(EvalError::InvalidParameters(
pos,
format!("multiply operation cannot be applied to two strings"),
))
}
(Value::Function(_), _) | (_, Value::Function(_)) => {
return Err(EvalError::InvalidParameters(
pos,
format!("multiply operation cannot be applied to functions"),
))
if args.is_empty() {
Ok(Value::Nil)
} else if args.len() == 1 {
eval(&args[0], ctx)
} else {
let mut acc = eval(&args[0], ctx)?;
for b in args.iter().skip(1) {
let b = eval(b, ctx)?;
acc = match (acc, b) {
(Value::Nil, b) => b,
(a, Value::Nil) => a,
(Value::I32(a), Value::I32(b)) => Value::I32(a * b),
(Value::String(a), Value::I32(b)) | (Value::I32(b), Value::String(a)) => {
Value::String(a.repeat(b.max(0) as usize))
}
(Value::String(_), Value::String(_)) => {
return Err(EvalError::InvalidParameters(
pos,
format!("multiply operation cannot be applied to two strings"),
))
}
(Value::Function(_), _) | (_, Value::Function(_)) => {
return Err(EvalError::InvalidParameters(
pos,
format!("multiply operation cannot be applied to functions"),
))
}
};
}
})

Ok(acc)
}
}
4 => {
// add
if args.len() != 2 {
return Err(EvalError::InvalidParameters(
pos,
format!(
"add operation requires exactly 2 parameters, got {}",
args.len()
),
));
}

let a = eval(&args[0], ctx)?;
let b = eval(&args[1], ctx)?;

Ok(match (a, b) {
(Value::Nil, b) => b,
(a, Value::Nil) => a,
(Value::I32(a), Value::I32(b)) => Value::I32(a + b),
(Value::String(a), Value::I32(b)) => Value::String(format!("{}{}", a, b)),
(Value::I32(a), Value::String(b)) => Value::String(format!("{}{}", a, b)),
(Value::String(a), Value::String(b)) => Value::String(format!("{}{}", a, b)),
(Value::Function(_), _) | (_, Value::Function(_)) => {
return Err(EvalError::InvalidParameters(
pos,
format!("add operation cannot be applied to functions"),
))
if args.is_empty() {
Ok(Value::Nil)
} else if args.len() == 1 {
eval(&args[0], ctx)
} else {
let mut acc = eval(&args[0], ctx)?;
for b in args.iter().skip(1) {
let b = eval(b, ctx)?;
acc = match (acc, b) {
(Value::Nil, b) => b,
(a, Value::Nil) => a,
(Value::I32(a), Value::I32(b)) => Value::I32(a + b),
(Value::String(a), Value::I32(b)) => Value::String(format!("{}{}", a, b)),
(Value::I32(a), Value::String(b)) => Value::String(format!("{}{}", a, b)),
(Value::String(a), Value::String(b)) => Value::String(format!("{}{}", a, b)),
(Value::Function(_), _) | (_, Value::Function(_)) => {
return Err(EvalError::InvalidParameters(
pos,
format!("add operation cannot be applied to functions"),
))
}
}
}
})

Ok(acc)
}
}
8 => {
// divide


Loading…
Cancel
Save