11import {
22 ArrowFuncDefNode ,
33 AssignNode , AstBlock , AstNode , BinOpNode , BracketObjectAccessNode , ConstNode , CreateArrayNode ,
4- CreateObjectNode , DotObjectAccessNode , ForNode , FunctionCallNode , FunctionDefNode , GetSingleVarNode , IfNode , OperationFuncs , Primitive , SetSingleVarNode , WhileNode
4+ CreateObjectNode , DotObjectAccessNode , ForNode , FuncDefNode , FunctionCallNode , FunctionDefNode , GetSingleVarNode , IfNode , OperationFuncs , Primitive , SetSingleVarNode , WhileNode
55} from '../common' ;
66import { Scope } from './scope' ;
77
88export class Evaluator {
99
10-
1110 evalBlock ( ast : AstBlock , scope : Scope ) : unknown {
1211 let lastResult = null ;
1312
1413 for ( let node of ast ?. funcs || [ ] ) {
1514 const funcDef = node as FunctionDefNode ;
1615
17- const ast = {
18- name : '' ,
19- type : 'func' ,
20- funcs : [ ] ,
21- body : funcDef . body
22- } as AstBlock ;
23-
2416 // a child scope needs to be created here
2517 const newScope = scope ;
2618
27- scope . set ( funcDef . name , ( ...args : unknown [ ] ) : unknown => {
28-
29- // set parameters into new scope, based incomming arguments
30- for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
31- if ( i >= funcDef . params . length ) {
32- break ;
33- // throw new Error('Too much parameters provided');
34- }
35- newScope . set ( funcDef . params [ i ] , args [ i ] ) ;
36- }
37- return this . evalBlock ( ast , newScope ) ;
38- }
19+ scope . set ( funcDef . name ,
20+ ( ...args : unknown [ ] ) : unknown => this . jspyFuncInvoker ( funcDef , scope , ...args )
3921 ) ;
22+ }
23+
24+ for ( const node of ast . body ) {
25+ lastResult = this . evalNode ( node , scope ) ;
26+ }
27+
28+ return lastResult ;
29+ }
30+
31+ async evalBlockAsync ( ast : AstBlock , scope : Scope ) : Promise < unknown > {
32+ let lastResult = null ;
33+
34+ for ( let node of ast ?. funcs || [ ] ) {
35+ const funcDef = node as FunctionDefNode ;
4036
37+ // a child scope needs to be created here
38+ const newScope = scope ;
39+
40+ scope . set ( funcDef . name ,
41+ ( ...args : unknown [ ] ) : unknown => this . jspyFuncInvoker ( funcDef , scope , ...args )
42+ ) ;
4143 }
4244
4345 for ( const node of ast . body ) {
@@ -47,6 +49,21 @@ export class Evaluator {
4749 return lastResult ;
4850 }
4951
52+ private jspyFuncInvoker ( funcDef : FuncDefNode , newScope : Scope , ...args : unknown [ ] ) : unknown {
53+
54+ const ast = { name : '' , type : 'func' , funcs : [ ] , body : funcDef . body } as AstBlock ;
55+
56+ // set parameters into new scope, based incomming arguments
57+ for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
58+ if ( i >= funcDef . params . length ) {
59+ break ;
60+ // throw new Error('Too much parameters provided');
61+ }
62+ newScope . set ( funcDef . params [ i ] , args [ i ] ) ;
63+ }
64+ return this . evalBlock ( ast , newScope ) ;
65+ }
66+
5067 private invokeFunction ( func : ( ...args : unknown [ ] ) => unknown , fps : unknown [ ] ) : unknown {
5168 if ( fps . length === 0 ) { return func ( ) ; }
5269 if ( fps . length === 1 ) { return func ( fps [ 0 ] ) ; }
@@ -143,28 +160,9 @@ export class Evaluator {
143160
144161 if ( node . type === "arrowFuncDef" ) {
145162 const arrowFuncDef = node as ArrowFuncDefNode ;
146-
147163 const newScope = scope ;
148- const ast = {
149- name : '' ,
150- type : 'func' ,
151- funcs : [ ] ,
152- body : arrowFuncDef . body
153- } as AstBlock ;
154-
155- const arrowFuncHandler = ( ...args : unknown [ ] ) : unknown => {
156- // set parameters into new scope, based incomming arguments
157- for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
158- if ( i >= arrowFuncDef . params . length ) {
159- break ;
160- // throw new Error('Too much parameters provided');
161- }
162- newScope . set ( arrowFuncDef . params [ i ] , args [ i ] ) ;
163- }
164- return this . evalBlock ( ast , newScope ) ;
165- }
166164
167- return arrowFuncHandler ;
165+ return ( ... args : unknown [ ] ) : unknown => this . jspyFuncInvoker ( arrowFuncDef , newScope , ... args ) ;
168166 }
169167
170168 if ( node . type === "funcCall" ) {
@@ -194,6 +192,12 @@ export class Evaluator {
194192 const lastPropertyName = ( targetNode . nestedProps [ targetNode . nestedProps . length - 1 ] as GetSingleVarNode ) . name
195193
196194 targetObject [ lastPropertyName ] = this . evalNode ( assignNode . source , scope ) ;
195+ } else if ( assignNode . target . type === 'bracketObjectAccess' ) {
196+ const targetNode = assignNode . target as BracketObjectAccessNode ;
197+ const keyValue = this . evalNode ( targetNode . bracketBody , scope ) as string | number ;
198+ const targetObject = scope . get ( targetNode . propertyName as string ) as Record < string , unknown > ;
199+
200+ targetObject [ keyValue ] = this . evalNode ( assignNode . source , scope ) ;
197201 } else {
198202 throw Error ( 'Not implemented Assign operation' ) ;
199203 // get chaining calls
@@ -206,7 +210,7 @@ export class Evaluator {
206210 const sbNode = node as BracketObjectAccessNode ;
207211 const key = this . evalNode ( sbNode . bracketBody , scope ) as string ;
208212 const obj = scope . get ( sbNode . propertyName as string ) as Record < string , unknown > ;
209- return obj [ key ] ;
213+ return ( obj [ key ] === undefined ) ? null : obj [ key ] ;
210214 }
211215
212216 if ( node . type === "dotObjectAccess" ) {
@@ -265,6 +269,4 @@ export class Evaluator {
265269 }
266270
267271 }
268-
269-
270- }
272+ }
0 commit comments