@@ -116,10 +116,29 @@ class Expression {
116116 static Invoke ( expression : Expression , ...args : Expression [ ] ) : InvocationExpression {
117117 return new InvocationExpression ( expression , args ) ;
118118 }
119+
120+ static New ( typeName : string , ...args : Expression [ ] ) : NewExpression {
121+ return new NewExpression ( typeName , args ) ;
122+ }
123+
124+ static Call ( obj : Expression , methodName : string , ...args : Expression [ ] ) : CallExpression {
125+ return new CallExpression ( obj , methodName , args ) ;
126+ }
127+
128+ static Member ( obj : Expression , memberName : string ) : MemberExpression {
129+ return new MemberExpression ( obj , memberName ) ;
130+ }
131+
132+ static Index ( obj : Expression , ...args : Expression [ ] ) : IndexExpression {
133+ return new IndexExpression ( obj , args ) ;
134+ }
119135}
120136
121137class ExpressionVisitor {
122138 Visit ( node : Expression ) : Expression {
139+ if ( node === null ) {
140+ return null ;
141+ }
123142 return node . Accept ( this ) ;
124143 }
125144
@@ -151,6 +170,22 @@ class ExpressionVisitor {
151170 return node . Update ( this . Visit ( node . expression ) , this . VisitMany ( node . args ) ) ;
152171 }
153172
173+ VisitCall ( node : CallExpression ) : Expression {
174+ return node . Update ( this . Visit ( node . obj ) , this . VisitMany ( node . args ) ) ;
175+ }
176+
177+ VisitNew ( node : NewExpression ) : Expression {
178+ return node . Update ( this . VisitMany ( node . args ) ) ;
179+ }
180+
181+ VisitMember ( node : MemberExpression ) : Expression {
182+ return node . Update ( this . Visit ( node . obj ) ) ;
183+ }
184+
185+ VisitIndex ( node : IndexExpression ) : Expression {
186+ return node . Update ( this . Visit ( node . obj ) , this . VisitMany ( node . args ) ) ;
187+ }
188+
154189 VisitMany < T extends Expression > ( nodes : T [ ] ) : T [ ] {
155190 var res = new Array < T > ( nodes . length ) ;
156191
@@ -325,6 +360,7 @@ class LambdaExpression<T extends Function> extends Expression {
325360 var comp = new LambdaCompiler ( ) ;
326361 comp . Visit ( this ) ;
327362 var code = comp . code ;
363+ code = code . replace ( / \" / g, "\\\"" ) ; // TODO: more escape sequences
328364 code = "new Function(\"return " + code + ";\")" ;
329365 code = code . replace ( / \r ? \n | \r / g, "" ) ;
330366 alert ( code ) ;
@@ -363,6 +399,136 @@ class InvocationExpression extends Expression {
363399 }
364400}
365401
402+ class CallExpression extends Expression {
403+ _expression : Expression ;
404+ _method : string ;
405+ _args : Expression [ ] ;
406+
407+ constructor ( expression : Expression , methodName : string , args : Expression [ ] ) {
408+ super ( ExpressionType . Call ) ;
409+ this . _expression = expression ;
410+ this . _method = methodName ;
411+ this . _args = args ;
412+ }
413+
414+ get obj ( ) : Expression {
415+ return this . _expression ;
416+ }
417+
418+ get method ( ) : string {
419+ return this . _method ;
420+ }
421+
422+ get args ( ) : Expression [ ] {
423+ return this . _args ;
424+ }
425+
426+ Accept ( visitor : ExpressionVisitor ) : Expression {
427+ return visitor . VisitCall ( this ) ;
428+ }
429+
430+ Update ( expression : Expression , args : Expression [ ] ) : CallExpression {
431+ if ( expression !== this . _expression || args !== this . _args ) {
432+ return new CallExpression ( expression , this . _method , args ) ;
433+ }
434+
435+ return this ;
436+ }
437+ }
438+
439+ class IndexExpression extends Expression {
440+ _expression : Expression ;
441+ _args : Expression [ ] ;
442+
443+ constructor ( expression : Expression , args : Expression [ ] ) {
444+ super ( ExpressionType . Index ) ;
445+ this . _expression = expression ;
446+ this . _args = args ;
447+ }
448+
449+ get obj ( ) : Expression {
450+ return this . _expression ;
451+ }
452+
453+ get args ( ) : Expression [ ] {
454+ return this . _args ;
455+ }
456+
457+ Accept ( visitor : ExpressionVisitor ) : Expression {
458+ return visitor . VisitIndex ( this ) ;
459+ }
460+
461+ Update ( expression : Expression , args : Expression [ ] ) : IndexExpression {
462+ if ( expression !== this . _expression || args !== this . _args ) {
463+ return new IndexExpression ( expression , args ) ;
464+ }
465+
466+ return this ;
467+ }
468+ }
469+
470+ class NewExpression extends Expression {
471+ _type : string ;
472+ _args : Expression [ ] ;
473+
474+ constructor ( typeName : string , args : Expression [ ] ) {
475+ super ( ExpressionType . New ) ;
476+ this . _type = typeName ;
477+ this . _args = args ;
478+ }
479+
480+ get type ( ) : string {
481+ return this . _type ;
482+ }
483+
484+ get args ( ) : Expression [ ] {
485+ return this . _args ;
486+ }
487+
488+ Accept ( visitor : ExpressionVisitor ) : Expression {
489+ return visitor . VisitNew ( this ) ;
490+ }
491+
492+ Update ( args : Expression [ ] ) : NewExpression {
493+ if ( args !== this . _args ) {
494+ return new NewExpression ( this . _type , args ) ;
495+ }
496+
497+ return this ;
498+ }
499+ }
500+
501+ class MemberExpression extends Expression {
502+ _obj : Expression ;
503+ _member : string ;
504+
505+ constructor ( obj : Expression , memberName : string ) {
506+ super ( ExpressionType . Member ) ;
507+ this . _obj = obj ;
508+ this . _member = memberName ;
509+ }
510+
511+ get obj ( ) : Expression {
512+ return this . _obj ;
513+ }
514+
515+ get member ( ) : string {
516+ return this . _member ;
517+ }
518+
519+ Accept ( visitor : ExpressionVisitor ) : Expression {
520+ return visitor . VisitMember ( this ) ;
521+ }
522+
523+ Update ( obj : Expression ) : MemberExpression {
524+ if ( obj !== this . _obj ) {
525+ return new MemberExpression ( obj , this . _member ) ;
526+ }
527+
528+ return this ;
529+ }
530+ }
531+
366532class LambdaCompiler extends ExpressionVisitor {
367533 _stack : string [ ] ;
368534
@@ -385,10 +551,13 @@ class LambdaCompiler extends ExpressionVisitor {
385551 value = "\"" + node . value + "\"" ; // TODO: escape characters
386552 }
387553 else if ( node . value instanceof Array ) {
388- value = "[" + node . value + "]" ; // TODO: proper formatting
554+ value = JSON . stringify ( node . value ) ;
555+ }
556+ else if ( node . value === undefined ) {
557+ value = "undefined" ;
389558 }
390559 else {
391- value = node . value . toString ( ) ;
560+ value = node . value . toString ( ) ; // TODO
392561 }
393562
394563 this . _stack . push ( value ) ;
@@ -417,7 +586,7 @@ class LambdaCompiler extends ExpressionVisitor {
417586 break ;
418587 }
419588
420- var res = i + "" + o ;
589+ var res = "(" + i + "" + o + ")" ;
421590 this . _stack . push ( res ) ;
422591
423592 return node ;
@@ -538,11 +707,36 @@ class LambdaCompiler extends ExpressionVisitor {
538707 }
539708
540709 VisitInvoke ( node : InvocationExpression ) : Expression {
541- this . VisitMany ( node . args ) ;
542710 this . Visit ( node . expression ) ;
711+ this . VisitMany ( node . args ) ;
712+
713+ var n = node . args . length ;
714+ var args = new Array < string > ( n ) ;
715+ for ( var i = 0 ; i < n ; i ++ ) {
716+ args [ n - i - 1 ] = this . _stack . pop ( ) ;
717+ }
718+
719+ var argList = args . join ( ", " ) ;
543720
544721 var func = this . _stack . pop ( ) ;
545722
723+ var res = func + "(" + argList + ")" ;
724+
725+ this . _stack . push ( res ) ;
726+
727+ return node ;
728+ }
729+
730+ VisitCall ( node : CallExpression ) : Expression {
731+ var res = "" ;
732+
733+ if ( node . obj !== null ) {
734+ this . Visit ( node . obj ) ;
735+ res = this . _stack . pop ( ) + "." ;
736+ }
737+
738+ this . VisitMany ( node . args ) ;
739+
546740 var n = node . args . length ;
547741 var args = new Array < string > ( n ) ;
548742 for ( var i = 0 ; i < n ; i ++ ) {
@@ -551,7 +745,61 @@ class LambdaCompiler extends ExpressionVisitor {
551745
552746 var argList = args . join ( ", " ) ;
553747
554- var res = func + "(" + argList + ")" ;
748+ res += node . method + "(" + argList + ")" ;
749+
750+ this . _stack . push ( res ) ;
751+
752+ return node ;
753+ }
754+
755+ VisitNew ( node : NewExpression ) : Expression {
756+ this . VisitMany ( node . args ) ;
757+
758+ var n = node . args . length ;
759+ var args = new Array < string > ( n ) ;
760+ for ( var i = 0 ; i < n ; i ++ ) {
761+ args [ n - i - 1 ] = this . _stack . pop ( ) ;
762+ }
763+
764+ var argList = args . join ( ", " ) ;
765+
766+ var res = "new " + node . type + "(" + argList + ")" ;
767+
768+ this . _stack . push ( res ) ;
769+
770+ return node ;
771+ }
772+
773+ VisitMember ( node : MemberExpression ) : Expression {
774+ var res = "" ;
775+
776+ if ( node . obj !== null ) {
777+ this . Visit ( node . obj ) ;
778+ res = this . _stack . pop ( ) + "." ;
779+ }
780+
781+ res += node . member ;
782+
783+ this . _stack . push ( res ) ;
784+
785+ return node ;
786+ }
787+
788+ VisitIndex ( node : IndexExpression ) : Expression {
789+ this . Visit ( node . obj ) ;
790+ var res = this . _stack . pop ( ) ;
791+
792+ this . VisitMany ( node . args ) ;
793+
794+ var n = node . args . length ;
795+ var args = new Array < string > ( n ) ;
796+ for ( var i = 0 ; i < n ; i ++ ) {
797+ args [ n - i - 1 ] = this . _stack . pop ( ) ;
798+ }
799+
800+ var argList = args . join ( ", " ) ;
801+
802+ res += "[" + argList + "]" ;
555803
556804 this . _stack . push ( res ) ;
557805
@@ -629,6 +877,10 @@ enum ExpressionType {
629877 UnaryPlus ,
630878 OnesComplement ,
631879 Condition ,
880+ New ,
881+ Call ,
882+ Member ,
883+ Index ,
632884}
633885
634886class Binder extends ExpressionVisitor {
@@ -669,8 +921,16 @@ class Binder extends ExpressionVisitor {
669921 }
670922}
671923
924+ var resources =
925+ {
926+ "my://xs" : [ 1 , 2 , 3 , 4 , 5 ] ,
927+ "my://ss" : [ "bar" , "foo" , "qux" ] ,
928+ "rx://operators/filter" : function ( xs : any [ ] , f : ( any ) => boolean) { return xs . filter ( f ) ; } ,
929+ "rx://operators/map" : function ( xs : any [ ] , f : ( any ) => any) { return xs . map ( f ) ; } ,
930+ } ;
931+
672932var x = Expression . Parameter ( "x" ) ;
673- var f =
933+ var f1 =
674934 Expression . Invoke (
675935 Expression . Parameter ( "rx://operators/map" ) ,
676936 Expression . Invoke (
@@ -696,22 +956,28 @@ var f =
696956 )
697957 ) ;
698958
699- var fvs = new FreeVariableScanner ( ) ;
700- fvs . Visit ( f ) ;
701-
702- var unbound = fvs . result ;
703-
704- var resources =
705- {
706- "my://xs" : [ 1 , 2 , 3 , 4 , 5 ] ,
707- "rx://operators/filter" : function ( xs : any [ ] , f : ( any ) => boolean) { return xs . filter ( f ) ; } ,
708- "rx://operators/map" : function ( xs : any [ ] , f : ( any ) => any) { return xs . map ( f ) ; } ,
709- } ;
959+ var f2 =
960+ Expression . Invoke (
961+ Expression . Parameter ( "rx://operators/map" ) ,
962+ Expression . Parameter ( "my://ss" ) ,
963+ Expression . Lambda < ( string ) => string> (
964+ Expression . Call (
965+ x ,
966+ "substring" ,
967+ Expression . Constant ( 1 )
968+ ) ,
969+ x
970+ )
971+ ) ;
710972
711973var binder = new Binder ( resources ) ;
712- var bound = Expression . Lambda < ( ) => number [ ] > ( binder . Visit ( f ) ) ;
713974
714- var compiled = bound . Compile ( ) ;
715- var res = compiled ( ) ;
716- alert ( res . join ( ", " ) ) ;
975+ var b1 = Expression . Lambda < ( ) => number [ ] > ( binder . Visit ( f1 ) ) ;
976+ var c1 = b1 . Compile ( ) ;
977+ var r1 = c1 ( ) ;
978+ alert ( r1 . join ( ", " ) ) ;
717979
980+ var b2 = Expression . Lambda < ( ) => string [ ] > ( binder . Visit ( f2 ) ) ;
981+ var c2 = b2 . Compile ( ) ;
982+ var r2 = c2 ( ) ;
983+ alert ( r2 . join ( ", " ) ) ;
0 commit comments