public ResolverValue ExecuteScalar(IActionQueryHost <ResolverValue> host, int _hardlimit = -1)
        {
            var r = Execute(host, _hardlimit);

            if (r != null)
            {
                return(r[r.Length - 1]);
            }
            else
            {
                return(new ResolverValue());
            }
        }
        public ResolverValue[] Execute(IActionQueryHost <ResolverValue> host, int hardlimit = -1)
        {
            int pc = 0, i;
            int _hardlimit = hardlimit;
            Stack <ResolverValue> _datastack = new Stack <ResolverValue>();

            //List<ResolverValue> _args = new List<ResolverValue>();
            ResolverValue[] _args = new ResolverValue[_MaxArgs];
            ResolverValue   val;
            Instruction     instr = Instruction.Empty;

            if (host == null)
            {
                throw new ActionQueryException <ResolverValue>("No host given to Execute", Instruction.Empty, null, 0);
            }
            IActionQueryHostControl <ResolverValue> tracer = null;

            if (host is IActionQueryHostControl <ResolverValue> tr)
            {
                if (tr.StartTrace(_program))
                {
                    tracer = tr;
                }
            }

            try {
                while (pc < _program.Length)
                {
                    instr = _program[pc];
                    if (_hardlimit == 0)
                    {
                        throw new ActionQueryException <ResolverValue>($"Hard limit {hardlimit} has been reached and the program has been stopped.", instr, _datastack.ToArray(), pc);
                    }
                    if (_hardlimit > 0)
                    {
                        _hardlimit--;
                    }

                    if (_datastack.Count < instr.ArgumentsCount)
                    {
                        throw new ActionQueryException <ResolverValue>("Stack underflow", instr, _datastack.ToArray(), pc);
                    }
                    else if (instr.ArgumentsCount > _MaxArgs)
                    {
                        throw new ActionQueryException <ResolverValue>("Too many arguments, up to _MaxArgs(def:16) are supported.", instr, _datastack.ToArray(), pc);
                    }
                    for (i = instr.ArgumentsCount - 1; i >= 0; i--)
                    {
                        _args[i] = _datastack.Pop();
                    }
                    if (tracer != null)
                    {
                        if (!tracer.Step(pc, instr, _args.Take(instr.ArgumentsCount).ToArray(), _datastack))
                        {
                            return(null);
                        }
                    }
                    // The PC should be incremented after performing the instruction.
                    switch (instr.Operation)
                    {
                    case Instructions.Call:
                        if (instr.Operand is string s)
                        {
                            val = host.CallProc(s, _args.Take(instr.ArgumentsCount).ToArray());
                            _datastack.Push(val);
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Call requires string operand.", instr, _datastack.ToArray(), pc);
                        }
                        pc++;
                        continue;

                    case Instructions.Jump:
                        if (instr.Operand is int x)
                        {
                            if (x >= 0 && x < _program.Length)
                            {
                                pc = x;
                                continue;
                            }
                            else
                            {
                                throw new ActionQueryException <ResolverValue>("Jump out of boundaries.", instr, _datastack.ToArray(), pc);
                            }
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Jump has invalid operand.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.JumpIfNot:
                        if (instr.Operand is int y)
                        {
                            if (y >= 0 && y < _program.Length)
                            {
                                if (instr.ArgumentsCount > 0)
                                {
                                    val = _args[0];
                                    if (host.IsTruthyOrFalsy(val))
                                    {
                                        pc++;
                                        continue;
                                    }
                                    else
                                    {
                                        pc = y;
                                        continue;
                                    }
                                }
                                else
                                {
                                    throw new ActionQueryException <ResolverValue>("Not enough arguments for JumpIfNot.", instr, _datastack.ToArray(), pc);
                                }
                            }
                            else
                            {
                                throw new ActionQueryException <ResolverValue>("Jump out of boundaries.", instr, _datastack.ToArray(), pc);
                            }
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Jump has invalid operand.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.NoOp:
                        pc++;
                        continue;

                    case Instructions.PushBool:
                        if (instr.Operand is bool)
                        {
                            _datastack.Push(host.FromBool((bool)instr.Operand));
                            pc++;
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.PushDouble:
                        if (instr.Operand is double)
                        {
                            _datastack.Push(host.FromDouble((double)instr.Operand));
                            pc++;
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.PushInt:
                        if (instr.Operand is int)
                        {
                            _datastack.Push(host.FromInt((int)instr.Operand));
                            pc++;
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.PushNull:
                        pc++;
                        _datastack.Push(host.FromNull());
                        continue;

                    case Instructions.PushParam:
                        if (instr.Operand is string)
                        {
                            pc++;
                            val = host.EvalParam(instr.Operand as string);
                            _datastack.Push(val);
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.PushVar:
                        if (instr.Operand is string varname)
                        {
                            pc++;
                            val = host.GetVar(varname);
                            _datastack.Push(val);
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.PullVar:
                        if (instr.Operand is string pullvarname)
                        {
                            pc++;
                            if (instr.ArgumentsCount > 1)
                            {
                                throw new ActionQueryException <ResolverValue>("Too many arguments.", instr, _datastack.ToArray(), pc);
                            }
                            if (instr.ArgumentsCount < 1)
                            {
                                throw new ActionQueryException <ResolverValue>("Not enough arguments.", instr, _datastack.ToArray(), pc);
                            }
                            val = host.SetVar(pullvarname, _args.FirstOrDefault());
                            _datastack.Push(val);
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.PushString:
                        if (instr.Operand is string)
                        {
                            pc++;
                            _datastack.Push(host.FromString((string)instr.Operand));
                            continue;
                        }
                        else
                        {
                            throw new ActionQueryException <ResolverValue>("Invalid operand type.", instr, _datastack.ToArray(), pc);
                        }

                    case Instructions.Dump:
                        pc++;
                        continue;

                    default:
                        throw new ActionQueryException <ResolverValue>("Unsupported instruction.", instr, _datastack.ToArray(), pc);
                    }
                }
                // Execution finished
                if (_datastack.Count > 0)
                {
                    return(_datastack.ToArray());
                }
                else
                {
                    return(null);
                }
            } catch (ActionQueryException <ResolverValue> ex) {
                throw ex;
            } catch (Exception ex) {
                throw new ActionQueryException <ResolverValue>("Exception in the ActionQuery's host:" + ex.Message, instr, _datastack.ToArray(), pc, ex);
            }
        }