コード例 #1
0
        internal static async Task <string> CompileAndRunTheExpression(MonoProxy proxy, MessageId msg_id, int scope_id, string expression, CancellationToken token)
        {
            FindVariableNMethodCall findVarNMethodCall = new FindVariableNMethodCall();
            string     retString;
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
				using System;
				public class CompileAndRunTheExpression
				{
					public string Evaluate()
					{
						return ("                         + expression + @").ToString(); 
					}
				}"                );

            FindThisExpression findThisExpression = new FindThisExpression(syntaxTree);
            var expressionTree = GetExpressionFromSyntaxTree(syntaxTree);

            findThisExpression.Visit(expressionTree);
            await findThisExpression.CheckIfIsProperty(proxy, msg_id, scope_id, token);

            syntaxTree = findThisExpression.syntaxTree;

            expressionTree = GetExpressionFromSyntaxTree(syntaxTree);
            findVarNMethodCall.Visit(expressionTree);

            syntaxTree = await findVarNMethodCall.ReplaceVars(syntaxTree, proxy, msg_id, scope_id, token);

            MetadataReference[] references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
            };

            CSharpCompilation compilation = CSharpCompilation.Create(
                "compileAndRunTheExpression",
                syntaxTrees: new [] { syntaxTree },
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (var ms = new MemoryStream())
            {
                EmitResult result = compilation.Emit(ms);
                ms.Seek(0, SeekOrigin.Begin);
                Assembly assembly = Assembly.Load(ms.ToArray());
                Type     type     = assembly.GetType("CompileAndRunTheExpression");
                object   obj      = Activator.CreateInstance(type);
                var      ret      = type.InvokeMember("Evaluate",
                                                      BindingFlags.Default | BindingFlags.InvokeMethod,
                                                      null,
                                                      obj,
                                                      findVarNMethodCall.values.ToArray());
                retString = ret.ToString();
            }
            return(retString);
        }
コード例 #2
0
        internal static async Task <JObject> CompileAndRunTheExpression(string expression, MemberReferenceResolver resolver, CancellationToken token)
        {
            expression = expression.Trim();
            if (!expression.StartsWith('('))
            {
                expression = "(" + expression + ")";
            }
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
                using System;
                public class CompileAndRunTheExpression
                {
                    public static object Evaluate()
                    {
                        return " + expression + @";
                    }
                }", cancellationToken: token);

            SyntaxNode expressionTree = GetExpressionFromSyntaxTree(syntaxTree);

            if (expressionTree == null)
            {
                throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree");
            }

            FindVariableNMethodCall findVarNMethodCall = new FindVariableNMethodCall();

            findVarNMethodCall.VisitInternal(expressionTree);

            // this fails with `"a)"`
            // because the code becomes: return (a));
            // and the returned expression from GetExpressionFromSyntaxTree is `a`!
            if (expressionTree.Kind() == SyntaxKind.IdentifierName || expressionTree.Kind() == SyntaxKind.ThisExpression)
            {
                string  varName = expressionTree.ToString();
                JObject value   = await resolver.Resolve(varName, token);

                if (value == null)
                {
                    throw new ReturnAsErrorException($"Cannot find member named '{varName}'.", "ReferenceError");
                }

                return(value);
            }

            IList <JObject> memberAccessValues = await ResolveMemberAccessExpressions(findVarNMethodCall.memberAccesses, resolver, token);

            // eg. "this.dateTime", "  dateTime.TimeOfDay"
            if (expressionTree.Kind() == SyntaxKind.SimpleMemberAccessExpression && findVarNMethodCall.memberAccesses.Count == 1)
            {
                return(memberAccessValues[0]);
            }

            IList <JObject> identifierValues = await ResolveIdentifiers(findVarNMethodCall.identifiers, resolver, token);

            syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, memberAccessValues, identifierValues, null);

            if (findVarNMethodCall.hasMethodCalls)
            {
                expressionTree = GetExpressionFromSyntaxTree(syntaxTree);

                findVarNMethodCall.VisitInternal(expressionTree);

                IList <JObject> methodValues = await ResolveMethodCalls(findVarNMethodCall.methodCall, findVarNMethodCall.memberAccessValues, resolver, token);

                syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, null, null, methodValues);
            }

            expressionTree = GetExpressionFromSyntaxTree(syntaxTree);
            if (expressionTree == null)
            {
                throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree");
            }

            MetadataReference[] references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
            };

            CSharpCompilation compilation = CSharpCompilation.Create(
                "compileAndRunTheExpression",
                syntaxTrees: new[] { syntaxTree },
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            SemanticModel semanticModel = compilation.GetSemanticModel(syntaxTree);

            CodeAnalysis.TypeInfo TypeInfo = semanticModel.GetTypeInfo(expressionTree, cancellationToken: token);

            using (var ms = new MemoryStream())
            {
                EmitResult result = compilation.Emit(ms, cancellationToken: token);
                if (!result.Success)
                {
                    var sb = new StringBuilder();
                    foreach (Diagnostic d in result.Diagnostics)
                    {
                        sb.Append(d.ToString());
                    }

                    throw new ReturnAsErrorException(sb.ToString(), "CompilationError");
                }

                ms.Seek(0, SeekOrigin.Begin);
                Assembly assembly = Assembly.Load(ms.ToArray());
                Type     type     = assembly.GetType("CompileAndRunTheExpression");

                object ret = type.InvokeMember("Evaluate",
                                               BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
                                               null,
                                               null,
                                               findVarNMethodCall.argValues.ToArray());

                return(JObject.FromObject(ConvertCSharpToJSType(ret, TypeInfo.Type)));
            }
        }
コード例 #3
0
        internal static async Task <JObject> CompileAndRunTheExpression(string expression, MemberReferenceResolver resolver, CancellationToken token)
        {
            expression = expression.Trim();
            if (!expression.StartsWith('('))
            {
                expression = "(" + expression + "\n)";
            }
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(expression + @";", cancellationToken: token);

            SyntaxNode expressionTree = syntaxTree.GetCompilationUnitRoot(token);

            if (expressionTree == null)
            {
                throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree");
            }
            FindVariableNMethodCall findVarNMethodCall = new FindVariableNMethodCall();

            findVarNMethodCall.VisitInternal(expressionTree);
            // this fails with `"a)"`
            // because the code becomes: return (a));
            // and the returned expression from GetExpressionFromSyntaxTree is `a`!
            if (expressionTree.Kind() == SyntaxKind.IdentifierName || expressionTree.Kind() == SyntaxKind.ThisExpression)
            {
                string  varName = expressionTree.ToString();
                JObject value   = await resolver.Resolve(varName, token);

                if (value == null)
                {
                    throw new ReturnAsErrorException($"Cannot find member named '{varName}'.", "ReferenceError");
                }

                return(value);
            }

            IList <JObject> memberAccessValues = await ResolveMemberAccessExpressions(findVarNMethodCall.memberAccesses, resolver, token);

            // eg. "this.dateTime", "  dateTime.TimeOfDay"
            if (expressionTree.Kind() == SyntaxKind.SimpleMemberAccessExpression && findVarNMethodCall.memberAccesses.Count == 1)
            {
                return(memberAccessValues[0]);
            }

            IList <JObject> identifierValues = await ResolveIdentifiers(findVarNMethodCall.identifiers, resolver, token);

            syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, memberAccessValues, identifierValues, null, null);

            if (findVarNMethodCall.hasMethodCalls)
            {
                expressionTree = syntaxTree.GetCompilationUnitRoot(token);

                findVarNMethodCall.VisitInternal(expressionTree);

                IList <JObject> methodValues = await ResolveMethodCalls(findVarNMethodCall.methodCall, findVarNMethodCall.memberAccessValues, resolver, token);

                syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, null, null, methodValues, null);
            }

            // eg. "elements[0]"
            if (findVarNMethodCall.hasElementAccesses)
            {
                expressionTree = syntaxTree.GetCompilationUnitRoot(token);

                findVarNMethodCall.VisitInternal(expressionTree);

                IList <JObject> elementAccessValues = await ResolveElementAccess(findVarNMethodCall.elementAccess, findVarNMethodCall.memberAccessValues, resolver, token);

                syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, null, null, null, elementAccessValues);
            }

            expressionTree = syntaxTree.GetCompilationUnitRoot(token);
            if (expressionTree == null)
            {
                throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree");
            }

            try
            {
                var newScript = script.ContinueWith(
                    string.Join("\n", findVarNMethodCall.variableDefinitions) + "\nreturn " + syntaxTree.ToString());

                var state = await newScript.RunAsync(cancellationToken : token);

                return(JObject.FromObject(ConvertCSharpToJSType(state.ReturnValue, state.ReturnValue?.GetType())));
            }
            catch (CompilationErrorException cee)
            {
                throw new ReturnAsErrorException($"Cannot evaluate '{expression}': {cee.Message}", "CompilationError");
            }
            catch (Exception ex)
            {
                throw new Exception($"Internal Error: Unable to run {expression}, error: {ex.Message}.", ex);
            }
        }