File tree Expand file tree Collapse file tree 2 files changed +45
-3
lines changed Expand file tree Collapse file tree 2 files changed +45
-3
lines changed Original file line number Diff line number Diff line change 38
38
} ;
39
39
} ;
40
40
41
+ var let = function ( input , ctx , rec ) {
42
+ var letCtx = new Ctx ( { } , ctx ) ;
43
+ input [ 1 ] . forEach ( function ( binding ) {
44
+ var name = binding [ 0 ] . value ;
45
+ var init = binding [ 1 ] ;
46
+ letCtx . scope [ name ] = interpret ( init , rec ? letCtx : ctx ) ;
47
+ } ) ;
48
+ return interpret ( input [ 2 ] , letCtx ) ;
49
+ }
50
+
41
51
var fn = function ( input , ctx ) {
42
52
return {
43
53
type : "function" ,
51
61
if ( ctx === undefined ) {
52
62
return interpret ( input , new Ctx ( library ) ) ;
53
63
} else if ( input instanceof Array ) {
54
- if ( input [ 0 ] . value === "lambda" ) {
55
- return lambda ( input , ctx ) ;
56
- } else {
64
+ switch ( input [ 0 ] . value ) {
65
+ case "lambda" : return lambda ( input , ctx ) ;
66
+ case "letrec" : return let ( input , ctx , true ) ;
67
+ case "let" : return let ( input , ctx , false ) ;
68
+ default :
57
69
var list = input . map ( function ( x ) { return interpret ( x , ctx ) ; } ) ;
58
70
if ( list [ 0 ] . type === "function" ) {
59
71
return list [ 0 ] . value ( list . slice ( 1 ) ) ;
Original file line number Diff line number Diff line change @@ -127,5 +127,35 @@ describe('tinyLisp', function() {
127
127
. toEqual ( 1 ) ;
128
128
} ) ;
129
129
} ) ;
130
+
131
+ describe ( 'let' , function ( ) {
132
+ it ( 'should eval inner expression w names bound' , function ( ) {
133
+ expect ( t . interpret ( t . parse ( "(let ((x 1) (y 2)) (x y))" ) ) ) . toEqual ( [ 1 , 2 ] ) ;
134
+ } ) ;
135
+
136
+ it ( 'should not expose parallel bindings to each other' , function ( ) {
137
+ // Expecting undefined for y to be consistent with normal
138
+ // identifier resolution in tinyLisp.
139
+ expect ( t . interpret ( t . parse ( "(let ((x 1) (y x)) (x y))" ) ) ) . toEqual ( [ 1 , undefined ] ) ;
140
+ } ) ;
141
+
142
+ it ( 'should accept empty binding list' , function ( ) {
143
+ expect ( t . interpret ( t . parse ( "(let () 42)" ) ) ) . toEqual ( 42 ) ;
144
+ } ) ;
145
+ } ) ;
146
+
147
+ describe ( 'letrec' , function ( ) {
148
+ it ( 'should expose previous bindings to later ones' , function ( ) {
149
+ expect ( t . interpret ( t . parse ( "(letrec ((x 42) (y x)) y)" ) ) ) . toEqual ( 42 ) ;
150
+ } ) ;
151
+
152
+ it ( 'should not expose later bindings to previous ones' , function ( ) {
153
+ expect ( t . interpret ( t . parse ( "(letrec ((x y) (y 42)) x)" ) ) ) . toEqual ( undefined ) ;
154
+ } ) ;
155
+
156
+ it ( 'should accept empty binding list' , function ( ) {
157
+ expect ( t . interpret ( t . parse ( "(letrec () 42)" ) ) ) . toEqual ( 42 ) ;
158
+ } ) ;
159
+ } ) ;
130
160
} ) ;
131
161
} ) ;
You can’t perform that action at this time.
0 commit comments