public DekiScriptExpression Visit(DekiScriptCall expr, DekiScriptExpressionEvaluationState state) { DekiScriptExpression prefix = expr.Prefix.VisitWith(this, state); DekiScriptExpression arguments = expr.Arguments.VisitWith(this, state); DekiScriptExpression result = expr.IsCurryOperation ? DekiScriptExpression.Curry(expr.Location, prefix, arguments) : DekiScriptExpression.Call(expr.Location, prefix, arguments); // check if prefix has been resolved to a uri and the arguments have all been resolved if ((prefix is DekiScriptUri) && (arguments is DekiScriptLiteral)) { // check if the uri can be resolved to a native idempotent function var descriptor = state.Runtime.ResolveRegisteredFunctionUri(((DekiScriptUri)result).Value); if ((descriptor != null) && descriptor.IsIdempotent) { // evaluate function, since it never changes return(state.Pop(DekiScriptExpression.Call(expr.Location, prefix, arguments).VisitWith(DekiScriptExpressionEvaluation.Instance, state))); } } return(result); }
public DekiScriptExpression Visit(DekiScriptCall expr, DekiScriptOptimizerState state) { DekiScriptExpression prefix = expr.Prefix.VisitWith(this, state); DekiScriptExpression arguments = expr.Arguments.VisitWith(this, state); DekiScriptExpression result = new DekiScriptCall(expr.Line, expr.Column, prefix, arguments, expr.IsCurryOperation); // check if prefix has been resolved to a uri and the arguments have all been resolved if ((prefix is DekiScriptUri) && (arguments is DekiScriptLiteral)) { DekiScriptFunction function; // check if the uri can be resolved to a native idempotent function if ( DekiScriptLibrary.Functions.TryGetValue(((DekiScriptUri)prefix).Value, out function) && (function is DekiScriptFunctionNative) && ((DekiScriptFunctionNative)function).IsIdempotent ) { // evaluate function, since it never changes return(new DekiScriptCall(expr.Line, expr.Column, prefix, arguments, false).Evaluate(state.Env)); } } return(result); }
public DekiScriptOutputBuffer.Range Visit(DekiScriptCall expr, DekiScriptExpressionEvaluationState state) { state.ThrowIfTimedout(); // evaluate prefix DekiScriptLiteral prefix = state.Pop(expr.Prefix.VisitWith(this, state)); if (prefix.ScriptType != DekiScriptType.URI) { if (prefix.ScriptType == DekiScriptType.NIL) { throw new DekiScriptUndefinedNameException(expr.Location, expr.Prefix.ToString()); } else { throw new DekiScriptBadTypeException(expr.Location, prefix.ScriptType, new[] { DekiScriptType.URI }); } } // evaluate arguments DekiScriptLiteral arguments = state.Pop(expr.Arguments.VisitWith(this, state)); if ((arguments.ScriptType != DekiScriptType.MAP) && (arguments.ScriptType != DekiScriptType.LIST)) { throw new DekiScriptBadTypeException(expr.Location, arguments.ScriptType, new[] { DekiScriptType.MAP, DekiScriptType.LIST }); } // check if the URI was curried DekiScriptUri uri = (DekiScriptUri)prefix; if (!uri.Arguments.IsNil) { switch (uri.Arguments.ScriptType) { case DekiScriptType.LIST: // append argument to list DekiScriptList list = new DekiScriptList((DekiScriptList)uri.Arguments); list.Add(arguments); arguments = list; break; case DekiScriptType.MAP: if (arguments.ScriptType == DekiScriptType.MAP) { // concatenate both maps DekiScriptMap map = new DekiScriptMap(); map.AddRange((DekiScriptMap)uri.Arguments); map.AddRange((DekiScriptMap)arguments); arguments = map; } else if ((arguments.ScriptType != DekiScriptType.LIST) || ((DekiScriptList)arguments).Value.Count > 0) { // we can't append a list to a map throw new DekiScriptBadTypeException(expr.Location, arguments.ScriptType, new[] { DekiScriptType.MAP }); } break; default: throw new DekiScriptBadTypeException(expr.Location, arguments.ScriptType, new[] { DekiScriptType.MAP, DekiScriptType.LIST }); } } // check if this is an invocation or curry operation if (expr.IsCurryOperation) { return(state.Push(new DekiScriptUri(uri.Value, arguments))); } // invoke function try { return(state.Push(state.Runtime.Invoke(expr.Location, uri.Value, arguments, state.Env))); } catch (DekiScriptFatalException) { throw; } catch (Exception e) { var descriptor = state.Runtime.ResolveRegisteredFunctionUri(uri.Value); throw new DekiScriptInvokeException(expr.Location, uri.Value, (descriptor != null) ? descriptor.Name : uri.Value.ToString(), e); } }
public DekiScriptLiteral Visit(DekiScriptCall expr, DekiScriptEnv env) { // evaluate prefix DekiScriptLiteral prefix = expr.Prefix.VisitWith(this, env); if (prefix.ScriptType != DekiScriptType.URI) { if (prefix.ScriptType == DekiScriptType.NIL) { throw new DekiScriptUndefinedNameException(expr.Line, expr.Column, expr.Prefix.ToString()); } else { throw new DekiScriptBadTypeException(expr.Line, expr.Column, prefix.ScriptType, new DekiScriptType[] { DekiScriptType.URI }); } } // evaluate arguments DekiScriptLiteral arguments = expr.Arguments.VisitWith(this, env); if ((arguments.ScriptType != DekiScriptType.MAP) && (arguments.ScriptType != DekiScriptType.LIST)) { throw new DekiScriptBadTypeException(expr.Line, expr.Column, arguments.ScriptType, new DekiScriptType[] { DekiScriptType.MAP, DekiScriptType.LIST }); } // check if the URI was curried DekiScriptUri uri = (DekiScriptUri)prefix; if (!uri.Arguments.IsNil) { switch (uri.Arguments.ScriptType) { case DekiScriptType.LIST: // append argument to list DekiScriptList list = new DekiScriptList((DekiScriptList)uri.Arguments); list.Add(arguments); arguments = list; break; case DekiScriptType.MAP: if (arguments.ScriptType == DekiScriptType.MAP) { // concatenate both maps DekiScriptMap map = new DekiScriptMap(); map.AddRange((DekiScriptMap)uri.Arguments); map.AddRange((DekiScriptMap)arguments); arguments = map; } else if ((arguments.ScriptType != DekiScriptType.LIST) || ((DekiScriptList)arguments).Value.Count > 0) { // we can't append a list to a map throw new DekiScriptBadTypeException(expr.Line, expr.Column, arguments.ScriptType, new DekiScriptType[] { DekiScriptType.MAP }); } break; default: throw new DekiScriptBadTypeException(expr.Line, expr.Column, arguments.ScriptType, new DekiScriptType[] { DekiScriptType.MAP, DekiScriptType.LIST }); } } // check if this is an invocation or curry operation if (expr.IsCurryOperation) { return(new DekiScriptUri(uri.Value, arguments)); } else { // invoke function return(Coroutine.Invoke(DekiScriptRuntime.Invoke, uri.Value, arguments, env, new Result <DekiScriptLiteral>()).Wait()); } }