public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { return(Value); }
public void ItEvaluatesUnaryOperators() { frame = frame .AddVariable("x2", 2) .AddVariable("t", true); Assert.AreEqual( "2".Replace("'", "\""), parser .Parse((x2) => + x2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "-2".Replace("'", "\""), parser .Parse((x2) => - x2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "false".Replace("'", "\""), parser .Parse((t) => !t) .Evaluate(executor, frame) .ToString() ); }
public override void ExitIfDef(VariableStateCalculatorGrammarParser.IfDefContext context) { ExecutionFrame frame = FrameStack.Pop(); FrameStack.Peek().Merge(frame); base.ExitIfDef(context); }
public void ItEvaluatesMemberAccess() { frame = frame .AddVariable("o", new JsonObject() .Add("foo", 42) ) .AddVariable("a", new JsonArray( "a", "b", "c" )); Assert.AreEqual( "42".Replace("'", "\""), parser .Parse((o) => o["foo"]) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "'a'".Replace("'", "\""), parser .Parse((a) => a[0]) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "'c'".Replace("'", "\""), parser .Parse((a) => a[-1]) .Evaluate(executor, frame) .ToString() ); }
public void SetUp() { parser = new LinqToAqlExpressionParser(); arango = new ArangoInMemory(); executor = arango.Executor; frame = new ExecutionFrame(); }
private IEnumerable <ExecutionFrame> MultiplyFrameByCollection( QueryExecutor executor, ExecutionFrame frame ) { IEnumerable <JsonValue> collection = CollectionExpression .Evaluate(executor, frame) .AsJsonArray; return(collection.Select( item => frame.AddVariable(VariableName, item) )); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { var result = new JsonArray(); foreach (var item in Items) { result.Add(item.Evaluate(executor, frame)); } return(result); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { var result = new JsonObject(); foreach (var pair in Items) { result.Add(pair.Key, pair.Value.Evaluate(executor, frame)); } return(result); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { JsonValue[] evaluatedArguments = Arguments.Select( a => a.Evaluate(executor, frame) ).ToArray(); return(executor.FunctionRepository.EvaluateFunction( FunctionName, evaluatedArguments )); }
public override void VisitIfStatement(IfStatementSyntax node) { if (node.Else != null) { // unexpected case throw new NotSupportedException(); } Int32 usedParameter = ExtractParameterFromCondition(node.Condition); FrameStack.Push(new ExecutionFrame(usedParameter)); base.VisitIfStatement(node); ExecutionFrame frame = FrameStack.Pop(); FrameStack.Peek().Merge(frame); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { if (!frame.Variables.ContainsKey(Name)) { throw new QueryExecutionException( $"Parameter {Name} cannot be found. Available variables: " + string.Join(", ", frame.Variables.Keys) ); } return(frame.Variables[Name]); }
private void ProcessIf(IfStatementSyntax ifStatement, Stack <ExecutionFrame> frameStack) { if (ifStatement.Else != null) { // unexpected case throw new NotSupportedException(); } Int32 usedParameter = ExtractParameterFromCondition(ifStatement.Condition); StatementSyntax ifBody = ifStatement.Statement; frameStack.Push(new ExecutionFrame(usedParameter)); ProcessIfImpl(ifBody, frameStack); ExecutionFrame frame = frameStack.Pop(); frameStack.Peek().Merge(frame); }
public void ItEvaluatesJsonObjectExpression() { frame = frame .AddVariable("x", 42); Assert.AreEqual( "{'foo':42,'bar':84}".Replace("'", "\""), parser .Parse((x) => new JsonObject() .Add("foo", x) .Add("bar", x * 2) ) .Evaluate(executor, frame) .ToString() ); }
private ExecutionState InternalCall(ContractMethod method, ExecutionFrame frame, Stack <VMObject> stack) { var args = new object[method.parameters.Length]; for (int i = 0; i < args.Length; i++) { var arg = stack.Pop(); var temp = arg.Data; if (temp is string) { switch (method.parameters[i]) { // TODO this currently is casting any type of object, not just addresses! // when a string is passed instead of an address we do an automatic lookup and replace case VMType.Object: var name = (string)temp; var runtime = (RuntimeVM)frame.VM; var address = runtime.Nexus.LookUpName(name); temp = address; break; case VMType.Number: var value = (string)temp; if (BigInteger.TryParse(value, out BigInteger number)) { temp = number; } break; } } args[i] = temp; } var result = this.Contract.CallInternalMethod(method.name, args); if (method.returnType != VMType.None) { var obj = VMObject.FromObject(result); stack.Push(obj); } return(ExecutionState.Running); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { JsonValue o = Operand.Evaluate(executor, frame); switch (ExpressionType) { case AqlExpressionType.UnaryPlus: return(AqlArithmetic.Plus(o)); case AqlExpressionType.UnaryMinus: return(AqlArithmetic.Minus(o)); case AqlExpressionType.Not: return(AqlArithmetic.Not(o)); } throw new QueryExecutionException( $"Cannot evaluate expression {ExpressionType} - not implemented" ); }
private ExecutionState InternalCall(ContractMethod method, ExecutionFrame frame, Stack <VMObject> stack) { var args = new object[method.parameters.Length]; for (int i = 0; i < args.Length; i++) { var arg = stack.Pop(); args[i] = arg.Data; } var result = this.Contract.CallInternalMethod((RuntimeVM)frame.VM, method.name, args); if (method.returnType != VMType.None) { var obj = VMObject.FromObject(result); stack.Push(obj); } return(ExecutionState.Running); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { JsonValue l = Left.Evaluate(executor, frame); JsonValue r = Right.Evaluate(executor, frame); switch (ExpressionType) { case AqlExpressionType.Add: return(AqlArithmetic.Add(l, r)); case AqlExpressionType.Subtract: return(AqlArithmetic.Subtract(l, r)); case AqlExpressionType.Multiply: return(AqlArithmetic.Multiply(l, r)); case AqlExpressionType.Divide: return(AqlArithmetic.Divide(l, r)); case AqlExpressionType.Modulo: return(AqlArithmetic.Modulo(l, r)); case AqlExpressionType.Equal: return(AqlArithmetic.Equal(l, r)); case AqlExpressionType.NotEqual: return(AqlArithmetic.NotEqual(l, r)); case AqlExpressionType.GreaterThan: return(AqlArithmetic.GreaterThan(l, r)); case AqlExpressionType.GreaterThanOrEqual: return(AqlArithmetic.GreaterThenOrEqual(l, r)); case AqlExpressionType.LessThan: return(AqlArithmetic.LessThan(l, r)); case AqlExpressionType.LessThanOrEqual: return(AqlArithmetic.LessThanOrEqual(l, r)); case AqlExpressionType.And: return(AqlArithmetic.And(l, r)); case AqlExpressionType.Or: return(AqlArithmetic.Or(l, r)); } throw new QueryExecutionException( $"Cannot evaluate expression {ExpressionType} - not implemented" ); }
public override JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame ) { JsonValue m = Member.Evaluate(executor, frame); JsonValue s = Subject.Evaluate(executor, frame); if (s.IsJsonArray) { if (!m.IsInteger) { return(JsonValue.Null); } int i = m.AsInteger; if (i < 0) { i += s.AsJsonArray.Count; } return(s[i]); } if (s.IsJsonObject) { if (!m.IsString) { return(JsonValue.Null); } return(s[m.AsString]); } return(JsonValue.Null); }
public override ExecutionState Execute(ExecutionFrame frame, Stack <VMObject> stack) { return(ExecutionState.Halt); }
public override ExecutionState Execute(ExecutionFrame frame, Stack <VMObject> stack) { if (this.Contract.ABI == null) { throw new VMException(frame.VM, $"VM nativecall failed: ABI is missing for contract '{this.Contract.Name}'"); } if (stack.Count <= 0) { throw new VMException(frame.VM, $"VM nativecall failed: method name not present in the VM stack {frame.Context.Name}"); } var stackObj = stack.Pop(); var methodName = stackObj.AsString(); var runtime = (RuntimeVM)frame.VM; if (methodName.Equals(SmartContract.ConstructorName, StringComparison.OrdinalIgnoreCase) && runtime.HasGenesis) { BigInteger usedQuota; if (Nexus.IsNativeContract(Contract.Name)) { usedQuota = 1024; // does not matter what number, just than its greater than 0 } else { usedQuota = runtime.CallNativeContext(NativeContractKind.Storage, nameof(StorageContract.GetUsedDataQuota), this.Contract.Address).AsNumber(); } if (usedQuota > 0) { throw new VMException(frame.VM, $"VM nativecall failed: constructor can only be called once"); } } var method = this.Contract.ABI.FindMethod(methodName); if (method == null) { throw new VMException(frame.VM, $"VM nativecall failed: contract '{this.Contract.Name}' does not have method '{methodName}' in its ABI"); } if (stack.Count < method.parameters.Length) { throw new VMException(frame.VM, $"VM nativecall failed: calling method {methodName} with {stack.Count} arguments instead of {method.parameters.Length}"); } ExecutionState result; BigInteger gasCost = 10; result = runtime.ConsumeGas(gasCost); if (result != ExecutionState.Running) { return(result); } var native = Contract as NativeContract; if (native != null) { using (var m = new ProfileMarker("InternalCall")) { try { native.SetRuntime(runtime); native.LoadFromStorage(runtime.Storage); result = InternalCall(native, method, frame, stack); native.SaveChangesToStorage(); } catch (ArgumentException ex) { throw new VMException(frame.VM, $"VM nativecall failed: calling method {methodName} with arguments of wrong type, " + ex.ToString()); } } } else { var custom = Contract as CustomContract; if (custom != null) { if (method.offset < 0) { throw new VMException(frame.VM, $"VM context call failed: abi contains invalid offset for {method.name}"); } #if SUSHI_MODE var debugPath = @"C:\Code\Poltergeist\Builds\Windows\debug.asm"; var disasm = new VM.Disassembler(custom.Script); var asm = string.Join("\n", disasm.Instructions.Select(x => x.ToString())); System.IO.File.WriteAllText(debugPath, asm); #endif var context = new ScriptContext(Contract.Name, custom.Script, (uint)method.offset); result = context.Execute(frame, stack); } else { throw new VMException(frame.VM, $"VM context call failed: unknown contract instance class {Contract.GetType().Name}"); } } // we terminate here execution, since it will be restarted in next context if (result == ExecutionState.Running) { result = ExecutionState.Halt; } return(result); }
/// <summary> /// Evaluates the expression to a concrete value /// in a given execution context /// </summary> public abstract JsonValue Evaluate( QueryExecutor executor, ExecutionFrame frame );
public override ExecutionState Execute(ExecutionFrame frame, Stack <VMObject> stack) { if (this.Contract.ABI == null) { #if DEBUG throw new VMDebugException(frame.VM, $"VM nativecall failed: ABI is missing for contract '{this.Contract.Name}'"); #else return(ExecutionState.Fault); #endif } if (stack.Count <= 0) { #if DEBUG throw new VMDebugException(frame.VM, $"VM nativecall failed: method name not present in the VM stack"); #else return(ExecutionState.Fault); #endif } var stackObj = stack.Pop(); var methodName = stackObj.AsString(); var method = this.Contract.ABI.FindMethod(methodName); if (method == null) { #if DEBUG throw new VMDebugException(frame.VM, $"VM nativecall failed: contract '{this.Contract.Name}' does not have method '{methodName}' in its ABI"); #else return(ExecutionState.Fault); #endif } if (stack.Count < method.parameters.Length) { #if DEBUG throw new VMDebugException(frame.VM, $"VM nativecall failed: calling method {methodName} with {stack.Count} arguments instead of {method.parameters.Length}"); #else return(ExecutionState.Fault); #endif } var runtime = (RuntimeVM)frame.VM; BigInteger gasCost; if (this.Contract.HasInternalMethod(methodName, out gasCost)) { ExecutionState result; try { result = runtime.ConsumeGas(gasCost); if (result == ExecutionState.Running) { Contract.LoadRuntimeData(runtime); result = InternalCall(method, frame, stack); Contract.UnloadRuntimeData(); } } catch (ArgumentException ex) { #if DEBUG throw new VMDebugException(frame.VM, $"VM nativecall failed: calling method {methodName} with arguments of wrong type, " + ex.ToString()); #else result = ExecutionState.Fault; #endif } // we terminate here execution, since it will be restarted in next context if (result == ExecutionState.Running) { result = ExecutionState.Halt; } return(result); } if (!(this.Contract is CustomContract customContract)) { #if DEBUG throw new VMDebugException(frame.VM, $"VM nativecall failed: contract '{this.Contract.Name}' is not a valid custom contract"); #else return(ExecutionState.Fault); #endif } stack.Push(stackObj); var context = new ScriptContext(customContract.Name, customContract.Script, true); return(context.Execute(frame, stack)); }
public void ItEvaluatesBinaryOperators() { frame = frame .AddVariable("x2", 2) .AddVariable("t", true); Assert.AreEqual( "5".Replace("'", "\""), parser .Parse((x2) => x2 + 3) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "5.5".Replace("'", "\""), parser .Parse((x2) => x2 + 3.5) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "'2asd'".Replace("'", "\""), parser .Parse((x2) => x2 + "asd") .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "1".Replace("'", "\""), parser .Parse((x2) => x2 - 1) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "8".Replace("'", "\""), parser .Parse((x2) => x2 * 4) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "0.5".Replace("'", "\""), parser .Parse((x2) => x2 / 4) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "2".Replace("'", "\""), parser .Parse((x2) => x2 % 3) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "true".Replace("'", "\""), parser .Parse((x2) => x2 == 2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "false".Replace("'", "\""), parser .Parse((x2) => x2 != 2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "false".Replace("'", "\""), parser .Parse((x2) => x2 > 2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "true".Replace("'", "\""), parser .Parse((x2) => x2 >= 2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "false".Replace("'", "\""), parser .Parse((x2) => x2 < 2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "true".Replace("'", "\""), parser .Parse((x2) => x2 <= 2) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "false".Replace("'", "\""), parser .Parse((t) => t && false) .Evaluate(executor, frame) .ToString() ); Assert.AreEqual( "true".Replace("'", "\""), parser .Parse((t) => t || true) .Evaluate(executor, frame) .ToString() ); }