Skip to content

Commit 18b61a3

Browse files
committed
replace "primitive" with "operator"
1 parent 9859ce9 commit 18b61a3

File tree

1 file changed

+78
-74
lines changed

1 file changed

+78
-74
lines changed

src/eval.rs

Lines changed: 78 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ use super::parse::{parse, Node};
1313
pub enum Error {
1414
UndefinedSymbol(Token),
1515
InvalidLeafNodeAtCompoundStart(Token),
16-
InvalidDefineExpression, // TODO: add src position
17-
InvalidLambdaExpression, // TODO: add src position
18-
InvalidLetExpression, // TODO: add src position
19-
InvalidPrimitiveExpression, // TODO: add src position
20-
InvalidPrimitiveOperation, // TODO: add src position
21-
InvalidPrimitiveOperand, // TODO: add src position
22-
InvalidApplication, // TODO: add src position
23-
InvalidIfExpression, // TODO: add src position
16+
InvalidDefineExpression, // TODO: add src position
17+
InvalidLambdaExpression, // TODO: add src position
18+
InvalidLetExpression, // TODO: add src position
19+
InvalidOperatorExpression, // TODO: add src position
20+
InvalidOperandValue, // TODO: add src position
21+
InvalidApplication, // TODO: add src position
22+
InvalidIfExpression, // TODO: add src position
2423
}
2524

2625
impl error::Error for Error {}
@@ -158,12 +157,12 @@ fn eval_compound(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
158157

159158
match &nodes[0] {
160159
Node::Leaf(tok) => match tok.t {
161-
TokenType::Identifier => match tok.literal.as_ref() {
160+
TokenType::Identifier => match tok.literal.as_str() {
162161
"define" => eval_define(nodes, env),
163162
"lambda" => eval_lambda(nodes, env),
164163
"let" => eval_let(nodes, env),
165-
"primitive" => eval_primitive(nodes, env),
166164
"if" => eval_if(nodes, env),
165+
op if is_operator(op) => eval_operator(nodes, env),
167166
_ => eval_application(nodes, env),
168167
},
169168
_ => Err(Error::InvalidLeafNodeAtCompoundStart(tok.clone())),
@@ -255,33 +254,38 @@ fn eval_let(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
255254
eval_sequence(bodies, next_env.clone())
256255
}
257256

258-
fn eval_primitive(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
259-
if nodes.len() < 2 {
260-
return Err(Error::InvalidPrimitiveExpression);
257+
fn is_operator(op: &str) -> bool {
258+
match op {
259+
"+" | "-" | "*" | "/" | "=" | ">" | ">=" | "<" | "<=" | "not" | "and" | "or" => true,
260+
_ => false,
261261
}
262+
}
262263

263-
let op = match &nodes[1] {
264+
fn eval_operator(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
265+
// We should have called is_operator() first, so the first node should
266+
// reflect the operator.
267+
let op = match &nodes[0] {
264268
Node::Leaf(tok) => match tok.t {
265269
TokenType::Identifier => &tok.literal,
266-
_ => return Err(Error::InvalidPrimitiveOperation),
270+
_ => unreachable!(),
267271
},
268-
Node::Compound(_) => return Err(Error::InvalidPrimitiveOperation),
272+
Node::Compound(_) => unreachable!(),
269273
};
270274

271275
match op.as_str() {
272276
"+" | "-" | "*" | "/" => {
273-
if nodes.len() != 4 {
274-
return Err(Error::InvalidPrimitiveOperation);
277+
if nodes.len() != 3 {
278+
return Err(Error::InvalidOperatorExpression);
275279
}
276280

277-
let a = match eval(&nodes[2], env.clone())? {
281+
let a = match eval(&nodes[1], env.clone())? {
278282
Value::Number(v) => v,
279-
_ => return Err(Error::InvalidPrimitiveOperand),
283+
_ => return Err(Error::InvalidOperandValue),
280284
};
281285

282-
let b = match eval(&nodes[3], env.clone())? {
286+
let b = match eval(&nodes[2], env.clone())? {
283287
Value::Number(v) => v,
284-
_ => return Err(Error::InvalidPrimitiveOperand),
288+
_ => return Err(Error::InvalidOperandValue),
285289
};
286290

287291
let v = match op.as_str() {
@@ -295,24 +299,24 @@ fn eval_primitive(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
295299
return Ok(Value::Number(v));
296300
}
297301
"=" => {
298-
if nodes.len() != 4 {
299-
return Err(Error::InvalidPrimitiveOperation);
302+
if nodes.len() != 3 {
303+
return Err(Error::InvalidOperatorExpression);
300304
}
301305

302-
let a = eval(&nodes[2], env.clone())?;
303-
let b = eval(&nodes[3], env.clone())?;
306+
let a = eval(&nodes[1], env.clone())?;
307+
let b = eval(&nodes[2], env.clone())?;
304308
Ok(Value::Boolean(a.eq(&b)))
305309
}
306310
">" | ">=" | "<" | "<=" => {
307-
if nodes.len() != 4 {
308-
return Err(Error::InvalidPrimitiveOperation);
311+
if nodes.len() != 3 {
312+
return Err(Error::InvalidOperatorExpression);
309313
}
310314

311-
let a = eval(&nodes[2], env.clone())?;
312-
let b = eval(&nodes[3], env.clone())?;
315+
let a = eval(&nodes[1], env.clone())?;
316+
let b = eval(&nodes[2], env.clone())?;
313317
let (a, b) = match (a, b) {
314318
(Value::Number(a), Value::Number(b)) => (a, b),
315-
_ => return Err(Error::InvalidPrimitiveOperation), // should be a runtime exception
319+
_ => return Err(Error::InvalidOperandValue),
316320
};
317321

318322
let v = match op.as_str() {
@@ -326,25 +330,25 @@ fn eval_primitive(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
326330
Ok(Value::Boolean(v))
327331
}
328332
"not" => {
329-
if nodes.len() != 3 {
330-
return Err(Error::InvalidPrimitiveOperation);
333+
if nodes.len() != 2 {
334+
return Err(Error::InvalidOperatorExpression);
331335
}
332336

333-
match eval(&nodes[2], env.clone())? {
337+
match eval(&nodes[1], env.clone())? {
334338
Value::Boolean(a) => Ok(Value::Boolean(!a)),
335-
_ => return Err(Error::InvalidPrimitiveOperation), // should be a runtime exception
339+
_ => return Err(Error::InvalidOperandValue),
336340
}
337341
}
338342
"and" | "or" => {
339-
if nodes.len() != 4 {
340-
return Err(Error::InvalidPrimitiveOperation);
343+
if nodes.len() != 3 {
344+
return Err(Error::InvalidOperatorExpression);
341345
}
342346

343-
let a = eval(&nodes[2], env.clone())?;
344-
let b = eval(&nodes[3], env.clone())?;
347+
let a = eval(&nodes[1], env.clone())?;
348+
let b = eval(&nodes[2], env.clone())?;
345349
let (a, b) = match (a, b) {
346350
(Value::Boolean(a), Value::Boolean(b)) => (a, b),
347-
_ => return Err(Error::InvalidPrimitiveOperation), // should be a runtime exception
351+
_ => return Err(Error::InvalidOperandValue),
348352
};
349353

350354
let v = match op.as_str() {
@@ -355,7 +359,7 @@ fn eval_primitive(nodes: &Vec<Node>, env: EnvPtr) -> Result<Value, Error> {
355359

356360
Ok(Value::Boolean(v))
357361
}
358-
_ => return Err(Error::InvalidPrimitiveOperation),
362+
_ => return Err(Error::InvalidOperatorExpression),
359363
}
360364
}
361365

@@ -404,46 +408,46 @@ fn test_eval() {
404408
("(define x 2) (let ((y x)) y)", Value::Number(2.0)),
405409
("(define x 2) (let ((x 3)) x)", Value::Number(3.0)),
406410
// closures (lambdas and applications)
407-
("((lambda (a b) (primitive + a b)) 1 2)", Value::Number(3.0)),
411+
("((lambda (a b) (+ a b)) 1 2)", Value::Number(3.0)),
408412
(
409-
"((lambda (a b) (primitive + a b) 4.0) 1 2)", // multibody lambda
413+
"((lambda (a b) (+ a b) 4.0) 1 2)", // multibody lambda
410414
Value::Number(4.0),
411415
),
412416
// local bindings (let)
413417
("(let ((x 1)) x)", Value::Number(1.0)),
414418
("(let ((x 1)) x 2)", Value::Number(2.0)),
415-
("(let ((x 1) (y 2)) (primitive + x y))", Value::Number(3.0)),
416-
("(let ((x (primitive + 1 3))) x)", Value::Number(4.0)),
419+
("(let ((x 1) (y 2)) (+ x y))", Value::Number(3.0)),
420+
("(let ((x (+ 1 3))) x)", Value::Number(4.0)),
417421
// primitives
418-
("(primitive + 1 1)", Value::Number(2.0)),
419-
("(primitive - 2 1)", Value::Number(1.0)),
420-
("(primitive * 2 3)", Value::Number(6.0)),
421-
("(primitive / 6 2)", Value::Number(3.0)),
422-
("(primitive = 1 1)", Value::Boolean(true)),
423-
("(primitive = 0 0)", Value::Boolean(true)),
424-
("(primitive = 1 0)", Value::Boolean(false)),
425-
("(primitive = #t #t)", Value::Boolean(true)),
426-
("(primitive = #f #f)", Value::Boolean(true)),
427-
("(primitive = #t #f)", Value::Boolean(false)),
428-
(r#"(primitive = "a" "a")"#, Value::Boolean(true)),
429-
(r#"(primitive = "b" "b")"#, Value::Boolean(true)),
430-
(r#"(primitive = "a" "b")"#, Value::Boolean(false)),
431-
("(primitive > 1 1)", Value::Boolean(false)),
432-
("(primitive > 1 0)", Value::Boolean(true)),
433-
("(primitive > 0 1)", Value::Boolean(false)),
434-
("(primitive < 1 1)", Value::Boolean(false)),
435-
("(primitive < 1 0)", Value::Boolean(false)),
436-
("(primitive < 0 1)", Value::Boolean(true)),
437-
("(primitive not #t)", Value::Boolean(false)),
438-
("(primitive not #f)", Value::Boolean(true)),
439-
("(primitive and #f #f)", Value::Boolean(false)),
440-
("(primitive and #f #t)", Value::Boolean(false)),
441-
("(primitive and #t #f)", Value::Boolean(false)),
442-
("(primitive and #t #t)", Value::Boolean(true)),
443-
("(primitive or #f #f)", Value::Boolean(false)),
444-
("(primitive or #f #t)", Value::Boolean(true)),
445-
("(primitive or #t #f)", Value::Boolean(true)),
446-
("(primitive or #t #t)", Value::Boolean(true)),
422+
("(+ 1 1)", Value::Number(2.0)),
423+
("(- 2 1)", Value::Number(1.0)),
424+
("(* 2 3)", Value::Number(6.0)),
425+
("(/ 6 2)", Value::Number(3.0)),
426+
("(= 1 1)", Value::Boolean(true)),
427+
("(= 0 0)", Value::Boolean(true)),
428+
("(= 1 0)", Value::Boolean(false)),
429+
("(= #t #t)", Value::Boolean(true)),
430+
("(= #f #f)", Value::Boolean(true)),
431+
("(= #t #f)", Value::Boolean(false)),
432+
(r#"(= "a" "a")"#, Value::Boolean(true)),
433+
(r#"(= "b" "b")"#, Value::Boolean(true)),
434+
(r#"(= "a" "b")"#, Value::Boolean(false)),
435+
("(> 1 1)", Value::Boolean(false)),
436+
("(> 1 0)", Value::Boolean(true)),
437+
("(> 0 1)", Value::Boolean(false)),
438+
("(< 1 1)", Value::Boolean(false)),
439+
("(< 1 0)", Value::Boolean(false)),
440+
("(< 0 1)", Value::Boolean(true)),
441+
("(not #t)", Value::Boolean(false)),
442+
("(not #f)", Value::Boolean(true)),
443+
("(and #f #f)", Value::Boolean(false)),
444+
("(and #f #t)", Value::Boolean(false)),
445+
("(and #t #f)", Value::Boolean(false)),
446+
("(and #t #t)", Value::Boolean(true)),
447+
("(or #f #f)", Value::Boolean(false)),
448+
("(or #f #t)", Value::Boolean(true)),
449+
("(or #t #f)", Value::Boolean(true)),
450+
("(or #t #t)", Value::Boolean(true)),
447451
// if
448452
("(if #t 1 2)", Value::Number(1.0)),
449453
("(if #f 1 2)", Value::Number(2.0)),

0 commit comments

Comments
 (0)