@@ -2,10 +2,10 @@ import {
22 ArrowFuncDefNode ,
33 AssignNode , AstBlock , AstNode , BinOpNode , BracketObjectAccessNode , ConstNode , CreateArrayNode ,
44 CreateObjectNode , DotObjectAccessNode , ForNode , FuncDefNode , FunctionCallNode , FunctionDefNode , GetSingleVarNode ,
5- IfNode , IsNullCoelsing , LogicalOpNode , OperationFuncs , Primitive , ReturnNode , SetSingleVarNode , WhileNode
5+ IfNode , IsNullCoelsing , LogicalOpNode , OperationFuncs , Primitive , RaiseNode , ReturnNode , SetSingleVarNode , TryExceptNode , WhileNode
66} from '../common' ;
7- import { JspyEvalError } from '../common/utils' ;
8- import { BlockContext , Scope } from './scope' ;
7+ import { JspyError , JspyEvalError } from '../common/utils' ;
8+ import { BlockContext , cloneContext , Scope } from './scope' ;
99
1010export class Evaluator {
1111
@@ -46,11 +46,13 @@ export class Evaluator {
4646 break ;
4747 }
4848 } catch ( err ) {
49- if ( err instanceof JspyEvalError ) {
49+ const loc = node . loc ? node . loc : [ 0 , 0 ]
50+ if ( err instanceof JspyError ) {
51+ throw err ;
52+ } else if ( err instanceof JspyEvalError ) {
5053 throw err ;
5154 } else {
52- const loc = node . loc ? node . loc : [ 0 , 0 ] ;
53- throw new JspyEvalError ( ast . name , loc [ 0 ] , loc [ 1 ] , err . message || err )
55+ throw new JspyEvalError ( blockContext . moduleName , loc [ 0 ] , loc [ 1 ] , err . message || err )
5456 }
5557 }
5658
@@ -64,10 +66,7 @@ export class Evaluator {
6466 const ast = Object . assign ( { } , funcDef . funcAst ) ;
6567 ast . type = 'func' ;
6668
67- const blockContext = {
68- moduleName : context . moduleName ,
69- blockScope : context . blockScope . clone ( )
70- } as BlockContext ;
69+ const blockContext = cloneContext ( context ) ;
7170
7271 // set parameters into new scope, based incomming arguments
7372 for ( let i = 0 ; i < args ?. length || 0 ; i ++ ) {
@@ -82,40 +81,45 @@ export class Evaluator {
8281 }
8382
8483 private invokeFunction ( func : ( ...args : unknown [ ] ) => unknown , fps : unknown [ ] ) : unknown {
85- if ( fps . length === 0 ) { return func ( ) ; }
86- if ( fps . length === 1 ) { return func ( fps [ 0 ] ) ; }
87- if ( fps . length === 2 ) { return func ( fps [ 0 ] , fps [ 1 ] ) ; }
88- if ( fps . length === 3 ) { return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] ) ; }
89- if ( fps . length === 4 ) {
90- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] ) ;
91- }
92- if ( fps . length === 5 ) {
93- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] ) ;
94- }
84+ try {
85+ if ( fps . length === 0 ) { return func ( ) ; }
86+ if ( fps . length === 1 ) { return func ( fps [ 0 ] ) ; }
87+ if ( fps . length === 2 ) { return func ( fps [ 0 ] , fps [ 1 ] ) ; }
88+ if ( fps . length === 3 ) { return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] ) ; }
89+ if ( fps . length === 4 ) {
90+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] ) ;
91+ }
92+ if ( fps . length === 5 ) {
93+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] ) ;
94+ }
9595
96- if ( fps . length === 6 ) {
97- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] ) ;
98- }
96+ if ( fps . length === 6 ) {
97+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] ) ;
98+ }
9999
100- if ( fps . length === 7 ) {
101- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] ) ;
102- }
100+ if ( fps . length === 7 ) {
101+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] ) ;
102+ }
103103
104- if ( fps . length === 8 ) {
105- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] , fps [ 7 ] ) ;
106- }
104+ if ( fps . length === 8 ) {
105+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] , fps [ 7 ] ) ;
106+ }
107107
108- if ( fps . length === 9 ) {
109- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] , fps [ 7 ] , fps [ 8 ] ) ;
110- }
108+ if ( fps . length === 9 ) {
109+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] , fps [ 7 ] , fps [ 8 ] ) ;
110+ }
111111
112- if ( fps . length === 10 ) {
113- return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] , fps [ 7 ] , fps [ 8 ] , fps [ 9 ] ) ;
114- }
112+ if ( fps . length === 10 ) {
113+ return func ( fps [ 0 ] , fps [ 1 ] , fps [ 2 ] , fps [ 3 ] , fps [ 4 ] , fps [ 5 ] , fps [ 6 ] , fps [ 7 ] , fps [ 8 ] , fps [ 9 ] ) ;
114+ }
115115
116- if ( fps . length > 10 ) {
117- throw Error ( 'Function has too many parameters. Current limitation is 10' ) ;
116+ if ( fps . length > 10 ) {
117+ throw Error ( 'Function has too many parameters. Current limitation is 10' ) ;
118+ }
119+ } catch ( err ) {
120+ throw new JspyError ( 'FuncCall' , err . message || err ) ;
118121 }
122+
119123 }
120124
121125 private evalNode ( node : AstNode , blockContext : BlockContext ) : unknown {
@@ -139,6 +143,52 @@ export class Evaluator {
139143 return ;
140144 }
141145
146+ if ( node . type === 'raise' ) {
147+ const raiseNode = node as RaiseNode ;
148+ const err = new JspyError ( raiseNode . errorName , raiseNode . errorMessage || "" ) ;
149+ err . line = raiseNode . loc [ 0 ] ;
150+ err . column = raiseNode . loc [ 1 ] ;
151+ err . moduleName = blockContext . moduleName ;
152+ throw err ;
153+ }
154+
155+ if ( node . type === 'tryExcept' ) {
156+ const tryNode = node as TryExceptNode ;
157+ try {
158+ this . evalBlock ( { name : blockContext . moduleName , type : 'trycatch' , body : tryNode . tryBody } as AstBlock , blockContext ) ;
159+
160+ if ( tryNode . elseBody ?. length || 0 > 0 ) {
161+ this . evalBlock ( { name : blockContext . moduleName , type : 'trycatch' , body : tryNode . elseBody } as AstBlock , blockContext ) ;
162+ }
163+ }
164+ catch ( err ) {
165+ if ( err instanceof JspyEvalError ) {
166+ // evaluation error should not be handled
167+ throw err ;
168+ } else {
169+ const name = ( err instanceof JspyError ) ? ( err as JspyError ) . name : typeof ( err ) ;
170+ const message = ( err instanceof JspyError ) ? ( err as JspyError ) . message : err ?? err . message ;
171+ const moduleName = ( err instanceof JspyError ) ? ( err as JspyError ) . moduleName : 0 ;
172+ const line = ( err instanceof JspyError ) ? ( err as JspyError ) . line : 0 ;
173+ const column = ( err instanceof JspyError ) ? ( err as JspyError ) . column : 0 ;
174+
175+ const firstExept = tryNode . exepts [ 0 ] ;
176+ const catchBody = firstExept . body ;
177+ const ctx = blockContext ; // cloneContext(blockContext);
178+ ctx . blockScope . set ( firstExept . error ?. alias || "error" , { name, message, line, column, moduleName } )
179+ this . evalBlock ( { name : blockContext . moduleName , type : 'trycatch' , body : catchBody } as AstBlock , ctx ) ;
180+ ctx . blockScope . set ( firstExept . error ?. alias || "error" , null )
181+ }
182+ }
183+ finally {
184+ if ( tryNode . finallyBody ?. length || 0 > 0 ) {
185+ this . evalBlock ( { name : blockContext . moduleName , type : 'trycatch' , body : tryNode . finallyBody } as AstBlock , blockContext ) ;
186+ }
187+ }
188+
189+ return ;
190+ }
191+
142192 if ( node . type === 'return' ) {
143193 const returnNode = node as ReturnNode ;
144194 blockContext . returnCalled = true ;
@@ -196,7 +246,7 @@ export class Evaluator {
196246 const name = ( node as GetSingleVarNode ) . name ;
197247
198248 const value = blockContext . blockScope . get ( ( node as GetSingleVarNode ) . name ) ;
199- if ( value === undefined ) {
249+ if ( value === undefined ) {
200250 throw new Error ( `Variable ${ name } is not defined.` ) ;
201251 }
202252 return value ;
@@ -235,7 +285,7 @@ export class Evaluator {
235285 if ( node . type === "funcCall" ) {
236286 const funcCallNode = node as FunctionCallNode ;
237287 const func = blockContext . blockScope . get ( funcCallNode . name ) as ( ...args : unknown [ ] ) => unknown ;
238- if ( typeof func !== 'function' ) {
288+ if ( typeof func !== 'function' ) {
239289 throw Error ( `'${ funcCallNode . name } ' is not a function or not defined.` )
240290 }
241291
@@ -305,7 +355,7 @@ export class Evaluator {
305355 const funcCallNode = nestedProp as FunctionCallNode ;
306356 const func = startObject [ funcCallNode . name ] as ( ...args : unknown [ ] ) => unknown ;
307357
308- if ( typeof func !== 'function' ) {
358+ if ( typeof func !== 'function' ) {
309359 throw Error ( `'${ funcCallNode . name } ' is not a function or not defined.` )
310360 }
311361
0 commit comments