@@ -13,14 +13,13 @@ use super::parse::{parse, Node};
1313pub 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
2625impl 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