@@ -215,86 +215,86 @@ void AddLocalVariableWithValue(string idName, JObject value)
215215 variableDefinitions . Add ( ConvertJSToCSharpLocalVariableAssignment ( idName , value ) ) ;
216216 }
217217 }
218+ }
218219
219- private static string ConvertJSToCSharpLocalVariableAssignment ( string idName , JToken variable )
220+ public static string ConvertJSToCSharpLocalVariableAssignment ( string idName , JToken variable )
221+ {
222+ string typeRet ;
223+ object valueRet ;
224+ JToken value = variable [ "value" ] ;
225+ string type = variable [ "type" ] . Value < string > ( ) ;
226+ string subType = variable [ "subtype" ] ? . Value < string > ( ) ;
227+ switch ( type )
220228 {
221- string typeRet ;
222- object valueRet ;
223- JToken value = variable [ "value" ] ;
224- string type = variable [ "type" ] . Value < string > ( ) ;
225- string subType = variable [ "subtype" ] ? . Value < string > ( ) ;
226- switch ( type )
227- {
228- case "string" :
229+ case "string" :
229230 {
230231 var str = value ? . Value < string > ( ) ;
231232 str = str . Replace ( "\" " , "\\ \" " ) ;
232233 valueRet = $ "\" { str } \" ";
233234 typeRet = "string" ;
234235 break ;
235236 }
236- case "symbol" :
237- {
238- valueRet = $ "'{ value ? . Value < char > ( ) } '";
239- typeRet = "char" ;
240- break ;
241- }
242- case "number" :
243- //casting to double and back to string would loose precision; so casting straight to string
244- valueRet = value ? . Value < string > ( ) ;
245- typeRet = "double" ;
246- break ;
247- case "boolean" :
248- valueRet = value ? . Value < string > ( ) . ToLowerInvariant ( ) ;
249- typeRet = "bool" ;
237+ case "symbol" :
238+ {
239+ valueRet = $ "'{ value ? . Value < char > ( ) } '";
240+ typeRet = "char" ;
250241 break ;
251- case "object" :
252- if ( variable [ "subtype" ] ? . Value < string > ( ) == "null" )
253- {
254- ( valueRet , typeRet ) = GetNullObject ( variable [ "className" ] ? . Value < string > ( ) ) ;
255- }
256- else
242+ }
243+ case "number" :
244+ //casting to double and back to string would loose precision; so casting straight to string
245+ valueRet = value ? . Value < string > ( ) ;
246+ typeRet = "double" ;
247+ break ;
248+ case "boolean" :
249+ valueRet = value ? . Value < string > ( ) . ToLowerInvariant ( ) ;
250+ typeRet = "bool" ;
251+ break ;
252+ case "object" :
253+ if ( variable [ "subtype" ] ? . Value < string > ( ) == "null" )
254+ {
255+ ( valueRet , typeRet ) = GetNullObject ( variable [ "className" ] ? . Value < string > ( ) ) ;
256+ }
257+ else
258+ {
259+ if ( ! DotnetObjectId . TryParse ( variable [ "objectId" ] , out DotnetObjectId objectId ) )
260+ throw new Exception ( $ "Internal error: Cannot parse objectId for var { idName } , with value: { variable } ") ;
261+
262+ switch ( objectId ? . Scheme )
257263 {
258- if ( ! DotnetObjectId . TryParse ( variable [ "objectId" ] , out DotnetObjectId objectId ) )
259- throw new Exception ( $ "Internal error: Cannot parse objectId for var { idName } , with value: { variable } ") ;
260-
261- switch ( objectId ? . Scheme )
262- {
263- case "valuetype" when variable [ "isEnum" ] ? . Value < bool > ( ) == true :
264- typeRet = variable [ "className" ] ? . Value < string > ( ) ;
265- valueRet = $ "({ typeRet } ) { value [ "value" ] . Value < double > ( ) } ";
266- break ;
267- case "object" :
268- default :
269- valueRet = "Newtonsoft.Json.Linq.JObject.FromObject(new {"
270- + $ "type = \" { type } \" "
271- + $ ", description = \" { variable [ "description" ] . Value < string > ( ) } \" "
272- + $ ", className = \" { variable [ "className" ] . Value < string > ( ) } \" "
273- + ( subType != null ? $ ", subtype = \" { subType } \" " : "" )
274- + ( objectId != null ? $ ", objectId = \" { objectId } \" " : "" )
275- + "})" ;
276- typeRet = "object" ;
277- break ;
278- }
264+ case "valuetype" when variable [ "isEnum" ] ? . Value < bool > ( ) == true :
265+ typeRet = variable [ "className" ] ? . Value < string > ( ) ;
266+ valueRet = $ "({ typeRet } ) { value [ "value" ] . Value < double > ( ) } ";
267+ break ;
268+ case "object" :
269+ default :
270+ valueRet = "Newtonsoft.Json.Linq.JObject.FromObject(new {"
271+ + $ "type = \" { type } \" "
272+ + $ ", description = \" { variable [ "description" ] . Value < string > ( ) } \" "
273+ + $ ", className = \" { variable [ "className" ] . Value < string > ( ) } \" "
274+ + ( subType != null ? $ ", subtype = \" { subType } \" " : "" )
275+ + ( objectId != null ? $ ", objectId = \" { objectId } \" " : "" )
276+ + "})" ;
277+ typeRet = "object" ;
278+ break ;
279279 }
280- break ;
281- case "void" :
282- ( valueRet , typeRet ) = GetNullObject ( "object" ) ;
283- break ;
284- default :
285- throw new Exception ( $ "Evaluate of this datatype { type } not implemented yet") ; //, "Unsupported");
286- }
287- return $ "{ typeRet } { idName } = { valueRet } ;";
288-
289- static ( string , string ) GetNullObject ( string className = "object" )
290- => ( "Newtonsoft.Json.Linq.JObject.FromObject(new {"
291- + $ "type = \" object\" ,"
292- + $ "description = \" object\" ,"
293- + $ "className = \" { className } \" ,"
294- + $ "subtype = \" null\" "
295- + "})" ,
296- "object" ) ;
280+ }
281+ break ;
282+ case "void" :
283+ ( valueRet , typeRet ) = GetNullObject ( "object" ) ;
284+ break ;
285+ default :
286+ throw new Exception ( $ "Evaluate of this datatype { type } not implemented yet") ; //, "Unsupported");
297287 }
288+ return $ "{ typeRet } { idName } = { valueRet } ;";
289+
290+ static ( string , string ) GetNullObject ( string className = "object" )
291+ => ( "Newtonsoft.Json.Linq.JObject.FromObject(new {"
292+ + $ "type = \" object\" ,"
293+ + $ "description = \" object\" ,"
294+ + $ "className = \" { className } \" ,"
295+ + $ "subtype = \" null\" "
296+ + "})" ,
297+ "object" ) ;
298298 }
299299
300300 private static async Task < IList < JObject > > Resolve < T > ( IList < T > collectionToResolve , MemberReferenceResolver resolver ,
@@ -368,13 +368,14 @@ async Task ReplaceMethodCall(InvocationExpressionSyntax method)
368368 }
369369 }
370370
371- private static async Task < IList < JObject > > ResolveElementAccess ( IEnumerable < ElementAccessExpressionSyntax > elementAccesses , Dictionary < string , JObject > memberAccessValues , MemberReferenceResolver resolver , CancellationToken token )
371+ private static async Task < IList < JObject > > ResolveElementAccess ( ExpressionSyntaxReplacer replacer , MemberReferenceResolver resolver , CancellationToken token )
372372 {
373373 var values = new List < JObject > ( ) ;
374374 JObject index = null ;
375+ IEnumerable < ElementAccessExpressionSyntax > elementAccesses = replacer . elementAccess ;
375376 foreach ( ElementAccessExpressionSyntax elementAccess in elementAccesses . Reverse ( ) )
376377 {
377- index = await resolver . Resolve ( elementAccess , memberAccessValues , index , token ) ;
378+ index = await resolver . Resolve ( elementAccess , replacer . memberAccessValues , index , replacer . variableDefinitions , token ) ;
378379 if ( index == null )
379380 throw new ReturnAsErrorException ( $ "Failed to resolve element access for { elementAccess } ", "ReferenceError" ) ;
380381 }
@@ -438,7 +439,7 @@ internal static async Task<JObject> CompileAndRunTheExpression(
438439
439440 replacer . VisitInternal ( expressionTree ) ;
440441
441- IList < JObject > elementAccessValues = await ResolveElementAccess ( replacer . elementAccess , replacer . memberAccessValues , resolver , token ) ;
442+ IList < JObject > elementAccessValues = await ResolveElementAccess ( replacer , resolver , token ) ;
442443
443444 syntaxTree = replacer . ReplaceVars ( syntaxTree , null , null , null , elementAccessValues ) ;
444445 }
@@ -447,42 +448,29 @@ internal static async Task<JObject> CompileAndRunTheExpression(
447448 if ( expressionTree == null )
448449 throw new Exception ( $ "BUG: Unable to evaluate { expression } , could not get expression from the syntax tree") ;
449450
451+ return await EvaluateSimpleExpression ( resolver , syntaxTree . ToString ( ) , expression , replacer . variableDefinitions , logger , token ) ;
452+ }
453+
454+ internal static async Task < JObject > EvaluateSimpleExpression (
455+ MemberReferenceResolver resolver , string compiledExpression , string orginalExpression , List < string > variableDefinitions , ILogger logger , CancellationToken token )
456+ {
450457 Script < object > newScript = script ;
451458 try
452459 {
453- newScript = script . ContinueWith (
454- string . Join ( "\n " , replacer . variableDefinitions ) + "\n return " + syntaxTree . ToString ( ) ) ;
460+ newScript = script . ContinueWith ( string . Join ( "\n " , variableDefinitions ) + "\n return " + compiledExpression + ";" ) ;
455461 var state = await newScript . RunAsync ( cancellationToken : token ) ;
456462 return JObject . FromObject ( resolver . ConvertCSharpToJSType ( state . ReturnValue , state . ReturnValue . GetType ( ) ) ) ;
457463 }
458464 catch ( CompilationErrorException cee )
459465 {
460- logger . LogDebug ( $ "Cannot evaluate '{ expression } '. Script used to compile it: { newScript . Code } { Environment . NewLine } { cee . Message } ") ;
461- throw new ReturnAsErrorException ( $ "Cannot evaluate '{ expression } ': { cee . Message } ", "CompilationError" ) ;
466+ logger . LogDebug ( $ "Cannot evaluate '{ orginalExpression } '. Script used to compile it: { newScript . Code } { Environment . NewLine } { cee . Message } ") ;
467+ throw new ReturnAsErrorException ( $ "Cannot evaluate '{ orginalExpression } ': { cee . Message } ", "CompilationError" ) ;
462468 }
463469 catch ( Exception ex )
464470 {
465- throw new Exception ( $ "Internal Error: Unable to run { expression } , error: { ex . Message } .", ex ) ;
471+ throw new Exception ( $ "Internal Error: Unable to run { orginalExpression } , error: { ex . Message } .", ex ) ;
466472 }
467473 }
468-
469- private static JObject ConvertCLRToJSType ( object v )
470- {
471- if ( v is JObject jobj )
472- return jobj ;
473-
474- if ( v is null )
475- return JObjectValueCreator . CreateNull ( "<unknown>" ) ? [ "value" ] as JObject ;
476-
477- string typeName = v . GetType ( ) . ToString ( ) ;
478- jobj = JObjectValueCreator . CreateFromPrimitiveType ( v ) ;
479- return jobj is not null
480- ? jobj [ "value" ] as JObject
481- : JObjectValueCreator . Create < object > ( value : null ,
482- type : "object" ,
483- description : v . ToString ( ) ,
484- className : typeName ) ? [ "value" ] as JObject ;
485- }
486474 }
487475
488476 internal sealed class ReturnAsErrorException : Exception
0 commit comments