public ObjectsFunctionCallExpression(ObjectMemberExpression callee, EvaluableExpression[] arguments, int startIndex, int endIndex) : base("ObjectsFunctionCall", startIndex, endIndex)
 {
     Callee    = callee;
     Arguments = arguments;
 }
Example #2
0
        private static EvaluableExpression TryGenerateObjectMemberIL(Type stateType, ObjectMemberExpression objectMemberExpression, ILGenerator iLGenerator, CompileContext compileContext)
        {
            var unresolvedExpression = objectMemberExpression;
            var stack = new Stack <(string memberName, object indexerValue)>();

            while (true)
            {
                var target = unresolvedExpression.Object;
                if (target is IdentifierExpression maybeIdentifier)
                {
                    if (unresolvedExpression.IsIndexer)
                    {
                        if (unresolvedExpression.Member is ConstantExpression constantExpression)
                        {
                            stack.Push(("", constantExpression.Value));
                            stack.Push((maybeIdentifier.Name, null));
                            break;
                        }
                        if (unresolvedExpression.Member is LiteralExpression literalExpression &&
                            literalExpression.LiteralValue.Value != null)
                        {
                            stack.Push(("", literalExpression.LiteralValue.Value));
                            stack.Push((maybeIdentifier.Name, null));
                            break;
                        }
                    }
                    else
                    {
                        var identifierExpression = (IdentifierExpression)unresolvedExpression.Member;
                        stack.Push((identifierExpression.Name, null));
                        stack.Push((maybeIdentifier.Name, null));
                        break;
                    }
                    stack.Clear();
                    return(objectMemberExpression);
                }
                var member = unresolvedExpression.Member;
                if (unresolvedExpression.IsIndexer)
                {
                    switch (member)
                    {
                    case ConstantExpression constantExpression:
                        stack.Push(("", constantExpression.Value));
                        break;

                    case LiteralExpression literalExpression when literalExpression.LiteralValue.Value != null:
                        stack.Push(("", literalExpression.LiteralValue.Value));
                        break;

                    default:
                        stack.Clear();
                        return(objectMemberExpression);
                    }
                }
                else
                {
                    var identifierExpression = (IdentifierExpression)unresolvedExpression.Member;
                    stack.Push((identifierExpression.Name, null));
                }
                if (target is ObjectMemberExpression objectMember)
                {
                    unresolvedExpression = objectMember;
                }
                else
                {
                    stack.Clear();
                    return(objectMemberExpression);
                }
            }
            var currentType = stateType;
            var first       = stack.Peek();

            if (string.Equals("this", first.memberName, StringComparison.Ordinal))
            {
                stack.Pop();
            }
            var readers = new List <Action <CompileContext, ILGenerator> > {
                (c, il) => il.Emit(OpCodes.Ldarg_1)
            };

            while (stack.Count > 0)
            {
                var(memberName, indexerValue) = stack.Pop();
                if (indexerValue != null)
                {
                    var indexerType = indexerValue.GetType();
                    var method      = currentType.GetMethod("Get", new[] { indexerType }) ?? currentType.GetMethod("get_Item", new[] { indexerType });
                    if (method != null)
                    {
                        currentType = method.ReturnType;
                        readers.Add((context, il) =>
                        {
                            var valueName = $"_v{NameCounter.GetCurrentCount()}";
                            GenerateValue(il, indexerValue, context, valueName, false);
                            il.Emit(OpCodes.Callvirt, method);
                        });
                        continue;
                    }
                    if (indexerValue is string stringValue)
                    {
                        memberName = stringValue;
                    }
                    else
                    {
                        return(objectMemberExpression);
                    }
                }
                if (!string.IsNullOrWhiteSpace(memberName))
                {
                    var propertyInfo = currentType.GetProperty(memberName);
                    if (propertyInfo != null && propertyInfo.CanRead)
                    {
                        var getter = propertyInfo.GetGetMethod();
                        if (getter != null)
                        {
                            currentType = propertyInfo.PropertyType;
                            readers.Add((context, il) => il.Emit(OpCodes.Callvirt, getter));
                            continue;
                        }
                    }
                    var fieldInfo = currentType.GetField(memberName);
                    if (fieldInfo != null)
                    {
                        currentType = fieldInfo.FieldType;
                        readers.Add((context, il) => il.Emit(OpCodes.Ldfld, fieldInfo));
                        continue;
                    }
                    var method = currentType.GetMethod("get_Item", new[] { typeof(string) }) ?? currentType.GetMethod("Get", new[] { typeof(string) })
                                 ?? currentType.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary <,>) &&
                                                                               x.GetGenericArguments()[0] == typeof(string))?.GetMethod("get_Item");
                    if (method != null)
                    {
                        currentType = method.ReturnType;
                        readers.Add((context, il) =>
                        {
                            il.Emit(OpCodes.Ldstr, memberName);
                            il.Emit(OpCodes.Callvirt, method);
                        });
                        continue;
                    }

                    var methodInfo = currentType.GetMethod(memberName);
                    if (methodInfo != null)
                    {
                        var type = currentType;
                        readers.Add((context, il) => GenerateNestedFunc2(type, methodInfo)(il));
                        currentType = typeof(Func <object[], object>);
                        continue;
                    }
                }
                return(objectMemberExpression);
            }
            foreach (var reader in readers)
            {
                reader(compileContext, iLGenerator);
            }
            if (currentType.IsValueType)
            {
                iLGenerator.Emit(OpCodes.Box, currentType);
            }
            return(null);
        }
Example #3
0
 private static void FormatObjectMemberExpression(int prefixLength, StringBuilder builder, ObjectMemberExpression objectMemberExpression, int count)
 {
     builder.AppendLine(AddPrefix(prefixLength, "object:"));
     Format(objectMemberExpression.Object, prefixLength + count, builder);
     builder.AppendLine(AddPrefix(prefixLength, $"member:indexer-{objectMemberExpression.IsIndexer}"));
     Format(objectMemberExpression.Member, prefixLength + count, builder);
 }
Example #4
0
            private EvaluableExpression GetVariable()
            {
                var chr  = se[index];
                var expr = chr == openParen?GetGroup() : GetIdentifier();

                SkipSpaces();
                chr = se[index];
                var start = index;

                while (true)
                {
                    if (chr == period)
                    {
                        if (option.NotAllowedMemberExpression)
                        {
                            throw new ParseException($"Member expression is not allowed at character {index}");
                        }
                        index++;
                        SkipSpaces();
                        expr = new ObjectMemberExpression(expr, GetIdentifier(), start, index, false);
                        SkipSpaces();
                        chr = se[index];
                    }
                    else if (chr == openSquareBracket)
                    {
                        if (option.NotAllowedIndexerExpression)
                        {
                            throw new ParseException($"Indexer expression is not allowed at character {index}");
                        }
                        index++;
                        expr = new ObjectMemberExpression(expr, GetExpression(), start, index, true);
                        SkipSpaces();
                        chr = se[index];
                        if (chr != closeSquareBracket)
                        {
                            throw new ParseException($"Unclosed [ at character {index}");
                        }
                        index++;
                        SkipSpaces();
                        chr = se[index];
                    }
                    else if (chr == openParen)
                    {
                        index++;
                        switch (expr)
                        {
                        case ObjectMemberExpression callee:
                            expr = new ObjectsFunctionCallExpression(callee, GetArguments(closeParen), start, index);
                            break;

                        case IdentifierExpression identifier:
                            var name     = identifier.Name;
                            var function = option.NakedFunctions.FirstOrDefault(f => f.Name == name);
                            if (function == null)
                            {
                                throw new ParseException($"Can not find naked function ({name}) at character {index - name.Length - 1}");
                            }
                            expr = new NakedFunctionCallExpression(function, GetArguments(closeParen), start, index);
                            break;
                        }
                        SkipSpaces();
                        chr = se[index];
                    }
                    else
                    {
                        break;
                    }
                }
                return(expr);
            }