1- import {
2- AssignNode , Ast , AstNode , BinOpNode , BracketObjectAccessNode , ConstNode , CreateArrayNode ,
3- CreateObjectNode , DotObjectAccessNode , FunctionCallNode , GetSingleVarNode , SetSingleVarNode
1+ import {
2+ ArrowFuncDefNode ,
3+ AssignNode , AstBlock , AstNode , BinOpNode , BracketObjectAccessNode , ConstNode , CreateArrayNode ,
4+ CreateObjectNode , DotObjectAccessNode , FunctionCallNode , FunctionDefNode , GetSingleVarNode , SetSingleVarNode
45} from '../common' ;
56import { Scope } from './scope' ;
67
@@ -14,26 +15,44 @@ const OperationFuncs: Record<string, (l: Primitive, r: Primitive) => Primitive>
1415
1516export class Evaluator {
1617
17- registerFunction ( funcName : string , fn : ( ) => unknown ) : Evaluator {
18- throw new Error ( 'Not implemented yet!' )
19- }
2018
21- registerInstance ( instanceName : string , instance : Record < string , unknown > ) : Evaluator {
22- throw new Error ( 'Not implemented yet!' )
23- }
19+ evalBlock ( ast : AstBlock , scope : Scope ) : unknown {
20+ let lastResult = null ;
2421
25- assignObject ( obj : Record < string , unknown > ) : Evaluator {
26- throw new Error ( 'Not implemented yet!' )
27- }
22+ for ( let node of ast ?. funcs || [ ] ) {
23+ const funcDef = node as FunctionDefNode ;
2824
29- eval ( ast : Ast , scope : Scope ) : Promise < unknown > {
30- let lastResult = null ;
25+ const ast = {
26+ name : '' ,
27+ type : 'func' ,
28+ funcs : [ ] ,
29+ body : funcDef . body
30+ } as AstBlock ;
31+
32+ // a child scope needs to be created here
33+ const newScope = scope ;
34+
35+ scope . set ( funcDef . name , ( ...args : unknown [ ] ) : unknown => {
36+
37+ // set parameters into new scope, based incomming arguments
38+ for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
39+ if ( i >= funcDef . params . length ) {
40+ break ;
41+ // throw new Error('Too much parameters provided');
42+ }
43+ newScope . set ( funcDef . params [ i ] , args [ i ] ) ;
44+ }
45+ return this . evalBlock ( ast , newScope ) ;
46+ }
47+ ) ;
48+
49+ }
3150
3251 for ( const node of ast . body ) {
3352 lastResult = this . evalNode ( node , scope ) ;
3453 }
3554
36- return Promise . resolve ( lastResult ) ;
55+ return lastResult ;
3756 }
3857
3958 private invokeFunction ( func : ( ...args : unknown [ ] ) => unknown , fps : unknown [ ] ) : unknown {
@@ -89,6 +108,32 @@ export class Evaluator {
89108 return OperationFuncs [ binOpNode . op ] ( left as Primitive , right as Primitive ) ;
90109 }
91110
111+ if ( node . type === "arrowFuncDef" ) {
112+ const arrowFuncDef = node as ArrowFuncDefNode ;
113+
114+ const newScope = scope ;
115+ const ast = {
116+ name : '' ,
117+ type : 'func' ,
118+ funcs : [ ] ,
119+ body : arrowFuncDef . body
120+ } as AstBlock ;
121+
122+ const arrowFuncHandler = ( ...args : unknown [ ] ) : unknown => {
123+ // set parameters into new scope, based incomming arguments
124+ for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
125+ if ( i >= arrowFuncDef . params . length ) {
126+ break ;
127+ // throw new Error('Too much parameters provided');
128+ }
129+ newScope . set ( arrowFuncDef . params [ i ] , args [ i ] ) ;
130+ }
131+ return this . evalBlock ( ast , newScope ) ;
132+ }
133+
134+ return arrowFuncHandler ;
135+ }
136+
92137 if ( node . type === "funcCall" ) {
93138 const funcCallNode = node as FunctionCallNode ;
94139 const func = scope . get ( funcCallNode . name ) as ( ...args : unknown [ ] ) => unknown ;
@@ -148,7 +193,7 @@ export class Evaluator {
148193 const func = startObject [ funcCallNode . name ] as ( ...args : unknown [ ] ) => unknown ;
149194 const pms = funcCallNode . paramNodes ?. map ( n => this . evalNode ( n , scope ) ) || [ ]
150195
151- startObject = this . invokeFunction ( func , pms ) ;
196+ startObject = this . invokeFunction ( func . bind ( startObject ) , pms ) ;
152197
153198 } else {
154199 throw Error ( "Can't resolve dotObjectAccess node" )
0 commit comments