44 CreateObjectNode , DotObjectAccessNode , ForNode , FuncDefNode , FunctionCallNode , FunctionDefNode , GetSingleVarNode ,
55 getStartLine ,
66 getTokenLoc ,
7- IfNode , IsNullCoelsing , LogicalOpNode , OperationFuncs , Primitive , RaiseNode , ReturnNode , SetSingleVarNode , TryExceptNode , WhileNode
7+ IfNode , ImportNode , IsNullCoelsing , LogicalOpNode , OperationFuncs , Primitive , RaiseNode , ReturnNode , SetSingleVarNode , TryExceptNode , WhileNode
88} from '../common' ;
99import { JspyEvalError , JspyError } from '../common/utils' ;
1010import { Evaluator } from './evaluator' ;
@@ -17,6 +17,19 @@ import { BlockContext, cloneContext, Scope } from './scope';
1717 */
1818export class EvaluatorAsync {
1919
20+ private moduleParser : ( modulePath : string ) => Promise < AstBlock > = ( ) => Promise . reject ( 'Module parser is not registered!' ) ;
21+ private blockContextFactory ?: ( modulePath : string ) => BlockContext ;
22+
23+ registerModuleParser ( moduleParser : ( modulePath : string ) => Promise < AstBlock > ) : EvaluatorAsync {
24+ this . moduleParser = moduleParser ;
25+ return this ;
26+ }
27+
28+ registerBlockContextFactory ( blockContextFactory : ( modulePath : string ) => BlockContext ) : EvaluatorAsync {
29+ this . blockContextFactory = blockContextFactory ;
30+ return this ;
31+ }
32+
2033 async evalBlockAsync ( ast : AstBlock , blockContext : BlockContext ) : Promise < unknown > {
2134 let lastResult = null ;
2235
@@ -35,6 +48,21 @@ export class EvaluatorAsync {
3548
3649 for ( const node of ast . body ) {
3750 if ( node . type === 'comment' ) { continue ; }
51+ if ( node . type === 'import' ) {
52+ const importNode = node as ImportNode ;
53+
54+ if ( typeof this . blockContextFactory !== 'function' ) {
55+ throw new Error ( 'blockContextFactory is not initialized' ) ;
56+ }
57+
58+ const moduleAst = await this . moduleParser ( importNode . module . name )
59+ const moduleBlockContext = this . blockContextFactory ( importNode . module . name ) ;
60+ await this . evalBlockAsync ( moduleAst , moduleBlockContext )
61+
62+ blockContext . blockScope . set ( importNode . module . alias || this . defaultModuleName ( importNode . module . name ) , moduleBlockContext . blockScope . getScope ( ) )
63+
64+ continue ;
65+ }
3866
3967 try {
4068 lastResult = await this . evalNodeAsync ( node , blockContext ) ;
@@ -69,28 +97,23 @@ export class EvaluatorAsync {
6997 return lastResult ;
7098 }
7199
100+ private defaultModuleName ( name : string ) : string {
101+ return name . substring ( name . lastIndexOf ( '/' ) + 1 , name . lastIndexOf ( '.' ) )
102+ }
103+
72104 private async jspyFuncInvokerAsync ( funcDef : FuncDefNode , context : BlockContext , ...args : unknown [ ] ) : Promise < unknown > {
73105
74106 const ast = Object . assign ( { } , funcDef . funcAst ) ;
75107 ast . type = 'func' ;
76108
77109 const blockContext = cloneContext ( context ) ;
78110
79- for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
80- if ( i >= funcDef . params . length ) {
81- break ;
82- // throw new Error('Too many parameters provided');
83- }
84- blockContext . blockScope . set ( funcDef . params [ i ] , args [ i ] ) ;
111+ // set parameters into new scope, based incomming arguments
112+ for ( let i = 0 ; i < funcDef . params ?. length || 0 ; i ++ ) {
113+ const argValue = args ?. length > i ? args [ i ] : null ;
114+ blockContext . blockScope . set ( funcDef . params [ i ] , argValue ) ;
85115 }
86116
87-
88- // // set parameters into new scope, based incomming arguments
89- // for (let i = 0; i < funcDef.params?.length || 0; i++) {
90- // const argValue = args?.length > i ? args[i] : null;
91- // blockContext.blockScope.set(funcDef.params[i], argValue);
92- // }
93-
94117 return await this . evalBlockAsync ( ast , blockContext ) ;
95118 }
96119
@@ -135,8 +158,7 @@ export class EvaluatorAsync {
135158
136159 private async evalNodeAsync ( node : AstNode , blockContext : BlockContext ) : Promise < unknown > {
137160 if ( node . type === 'import' ) {
138- // skip this for now. As modules are implemented externally
139- return null ;
161+ throw new Error ( 'Import should be defined at the start' ) ;
140162 }
141163
142164 if ( node . type === 'comment' ) {
0 commit comments