Esempio n. 1
0
        public override void GenerateCode(CodeGeneration.CodeGenerator cg)
        {
            var arrayinfo = TypeInfo.ArrayFromTypeInfo(Scope.ResolveType(TypeNode.TypeName));
            //to get the length
            LocalBuilder length = cg.IlGenerator.DeclareLocal(typeof(int));
            LocalBuilder count  = cg.IlGenerator.DeclareLocal(typeof(int));
            LocalBuilder arr    = cg.IlGenerator.DeclareLocal(arrayinfo.GetILType());

            Label initloopbegin = cg.IlGenerator.DefineLabel();
            Label initloopend   = cg.IlGenerator.DefineLabel();

            //set the count to zero
            cg.IlGenerator.Emit(OpCodes.Ldc_I4_0);
            cg.IlGenerator.Emit(OpCodes.Stloc, count);
            LengthExpression.GenerateCode(cg);
            cg.IlGenerator.Emit(OpCodes.Dup);
            //get the length
            cg.IlGenerator.Emit(OpCodes.Stloc, length);
            cg.IlGenerator.Emit(OpCodes.Newarr, arrayinfo.TargetType.GetILType());
            cg.IlGenerator.Emit(OpCodes.Stloc, arr);

            //make the initialization loop
            cg.IlGenerator.MarkLabel(initloopbegin);

            //make the comparison and jmp to end if does not hold
            cg.IlGenerator.Emit(OpCodes.Ldloc, count);
            cg.IlGenerator.Emit(OpCodes.Ldloc, length);
            cg.IlGenerator.Emit(OpCodes.Bge, initloopend);

            //Evaluate the expr and store it
            cg.IlGenerator.Emit(OpCodes.Ldloc, arr);
            cg.IlGenerator.Emit(OpCodes.Ldloc, count);
            InitExpression.GenerateCode(cg);
            cg.IlGenerator.Emit(OpCodes.Stelem, arrayinfo.TargetType.GetILType());

            //increase count and jmp to begin
            cg.IlGenerator.Emit(OpCodes.Ldloc, count);
            cg.IlGenerator.Emit(OpCodes.Ldc_I4_1);
            cg.IlGenerator.Emit(OpCodes.Add);
            cg.IlGenerator.Emit(OpCodes.Stloc, count);
            cg.IlGenerator.Emit(OpCodes.Br, initloopbegin);
            cg.IlGenerator.MarkLabel(initloopend);

            //leave the arr reference in the top of the stack
            cg.IlGenerator.Emit(OpCodes.Ldloc, arr);
        }
Esempio n. 2
0
        public bool TryParse <T>(string source, ref int index, [NotNullWhen(true)] out JsonPathExpression?expression, [NotNullWhen(false)] out string?errorMessage)
        {
            PathExpression <T> node;

            var isLocal = source[index] == '@';

            if (!JsonPathParser.TryParse(source, ref index, out var path, out errorMessage) &&
                // Swallow this error from the path parser and assume the path just ended.
                // If it's really a syntax error, the expression parser should catch it.
                errorMessage != "Unrecognized JSON Path element.")
            {
                expression = null !;
                return(false);
            }

            var lastOp = path !.Operators.Last();

            if (lastOp is NameOperator name)
            {
                path.Operators.Remove(name);
                if (name.Name == "indexOf")
                {
                    if (source[index] != '(')
                    {
                        errorMessage = "Expected '('.  'indexOf' operator requires a parameter.";
                        expression   = null !;
                        return(false);
                    }

                    index++;
                    if (!JsonParser.TryParse(source, ref index, out var parameter, out errorMessage, true) &&
                        // Swallow this error from the JSON parser and assume the value just ended.
                        // If it's really a syntax error, the expression parser should catch it.
                        errorMessage != "Expected \',\', \']\', or \'}\'.")
                    {
                        errorMessage = $"Error parsing parameter for 'indexOf' expression: {errorMessage}.";
                        expression   = null !;
                        return(false);
                    }

                    if (source[index] != ')')
                    {
                        errorMessage = "Expected ')'.";
                        expression   = null !;
                        return(false);
                    }

                    index++;
                    node = new IndexOfExpression <T>(path, isLocal, parameter !);
                }
                else
                {
                    node = new NameExpression <T>(path, isLocal, name.Name);
                }
            }
            else if (lastOp is LengthOperator length)
            {
                path.Operators.Remove(length);
                node = new LengthExpression <T>(path, isLocal);
            }
            else if (lastOp is ArrayOperator array)
            {
                path.Operators.Remove(array);
                var query    = array.Query as SliceQuery;
                var constant = query?.Slices.FirstOrDefault <Slice?>()?.Index;
                if (query == null || query.Slices.Count() != 1 || !constant.HasValue)
                {
                    errorMessage = "JSON Path expression indexers only support single constant values.";
                    expression   = null !;
                    return(false);
                }

                node = new ArrayIndexExpression <T>(path, isLocal, constant.Value);
            }
            else
            {
                throw new NotImplementedException();
            }

            expression = new PathValueExpression <T>(node);
            return(true);
        }
        public string TryParse <T>(string source, ref int index, out JsonPathExpression expression)
        {
            expression = null;
            PathExpression <T> node;

            var isLocal = source[index] == '@';
            var error   = JsonPathParser.Parse(source, ref index, out JsonPath path);

            // Swallow this error from the path parser and assume the path just ended.
            // If it's really a syntax error, the expression parser should catch it.
            if (error != null && error != "Unrecognized JSON Path element.")
            {
                return(error);
            }

            var lastOp = path.Operators.Last();

            if (lastOp is NameOperator name)
            {
                path.Operators.Remove(name);
                if (name.Name == "indexOf")
                {
                    if (source[index] != '(')
                    {
                        return("Expected '('.  'indexOf' operator requires a parameter.");
                    }

                    index++;
                    error = JsonParser.Parse(source, ref index, out JsonValue parameter, true);
                    // Swallow this error from the JSON parser and assume the value just ended.
                    // If it's really a syntax error, the expression parser should catch it.
                    if (error != null && error != "Expected \',\', \']\', or \'}\'.")
                    {
                        return($"Error parsing parameter for 'indexOf' expression: {error}.");
                    }

                    if (source[index] != ')')
                    {
                        return("Expected ')'.");
                    }

                    index++;
                    node = new IndexOfExpression <T>
                    {
                        Path      = path,
                        IsLocal   = isLocal,
                        Parameter = parameter
                    };
                }
                else
                {
                    node = new NameExpression <T>
                    {
                        Path    = path,
                        IsLocal = isLocal,
                        Name    = name.Name
                    }
                };
            }
            else if (lastOp is LengthOperator length)
            {
                path.Operators.Remove(length);
                node = new LengthExpression <T>
                {
                    Path    = path,
                    IsLocal = isLocal
                };
            }
            else if (lastOp is ArrayOperator array)
            {
                path.Operators.Remove(array);
                var query    = array.Query as SliceQuery;
                var constant = query?.Slices.FirstOrDefault()?.Index;
                if (query == null || query.Slices.Count() != 1 || !constant.HasValue)
                {
                    return("JSON Path expression indexers only support single constant values.");
                }

                node = new ArrayIndexExpression <T>
                {
                    Path    = path,
                    IsLocal = isLocal,
                    Index   = constant.Value
                };
            }
            else
            {
                throw new NotImplementedException();
            }

            expression = new PathValueExpression <T> {
                Path = node
            };
            return(null);
        }