public DekiScriptExpression Visit(DekiScriptAccess expr, DekiScriptExpressionEvaluationState state) { DekiScriptExpression prefix = expr.Prefix.VisitWith(this, state); DekiScriptExpression index = expr.Index.VisitWith(this, state); DekiScriptAccess access = (DekiScriptAccess)DekiScriptExpression.Access(expr.Location, prefix, index); if ((prefix is DekiScriptLiteral) && (index is DekiScriptLiteral)) { DekiScriptLiteral result = DekiScriptExpressionEvaluation.Instance.Evaluate(access, state, false); // check if result is a property if (DekiScriptRuntime.IsProperty(result)) { // retrieve property information var descriptor = state.Runtime.ResolveRegisteredFunctionUri(((DekiScriptUri)result).Value); if ((descriptor != null) && descriptor.IsIdempotent) { // evaluate property, since it never changes return(state.Runtime.EvaluateProperty(expr.Location, result, state.Env)); } return(DekiScriptExpression.Call(expr.Location, result, new DekiScriptList())); } return(result); } return(access); }
public DekiScriptExpression Visit(DekiScriptAccess expr, DekiScriptOptimizerState state) { DekiScriptExpression prefix = expr.Prefix.VisitWith(this, state); DekiScriptExpression index = expr.Index.VisitWith(this, state); DekiScriptAccess access = new DekiScriptAccess(expr.Line, expr.Column, prefix, index); if ((prefix is DekiScriptLiteral) && (index is DekiScriptLiteral)) { // BUGBUGBUG (steveb): don't eval properties! DekiScriptLiteral result = DekiScriptExpressionEvaluation.Instance.Evaluate(access, state.Env, false); // check if result is a property if (DekiScriptRuntime.IsProperty(result)) { // retrieve property information DekiScriptFunction function; if (DekiScriptLibrary.Functions.TryGetValue(((DekiScriptUri)result).Value, out function)) { if (function is DekiScriptFunctionNative) { DekiScriptFunctionNative native = (DekiScriptFunctionNative)function; // check if function is idempotent; if so, execute it if (native.IsIdempotent) { // evaluate property, since it never changes return(DekiScriptRuntime.EvaluateProperty(result, state.Env)); } } } return(new DekiScriptCall(expr.Line, expr.Column, result, new DekiScriptList(), false)); } return(result); } return(access); }
internal DekiScriptLiteral Evaluate(DekiScriptAccess expr, DekiScriptExpressionEvaluationState state, bool evaluateProperties) { DekiScriptLiteral prefix = state.Pop(expr.Prefix.VisitWith(this, state)); DekiScriptLiteral index = state.Pop(expr.Index.VisitWith(this, state)); switch (prefix.ScriptType) { case DekiScriptType.MAP: { DekiScriptLiteral result = ((DekiScriptMap)prefix)[index]; if (evaluateProperties) { result = state.Runtime.EvaluateProperty(expr.Location, result, state.Env); } return(result); } case DekiScriptType.LIST: { DekiScriptLiteral value = DekiScriptExpression.Constant(index.AsNumber()); DekiScriptLiteral result = ((DekiScriptList)prefix)[value]; if (evaluateProperties) { result = state.Runtime.EvaluateProperty(expr.Location, result, state.Env); } return(result); } case DekiScriptType.URI: { DekiScriptUri uri = (DekiScriptUri)prefix; // coerce the index type to STR index = DekiScriptExpression.Constant(index.AsString()); if (index.ScriptType != DekiScriptType.STR) { throw new DekiScriptBadTypeException(expr.Location, index.ScriptType, new[] { DekiScriptType.STR }); } // curry the argument DekiScriptList args; if (!uri.Arguments.IsNil) { // the uri already has curried parameters, make sure they are in LIST format; otherwise fail if (uri.Arguments.ScriptType != DekiScriptType.LIST) { throw new DekiScriptBadTypeException(expr.Location, uri.Arguments.ScriptType, new[] { DekiScriptType.NIL, DekiScriptType.LIST }); } args = new DekiScriptList((DekiScriptList)uri.Arguments); } else { args = new DekiScriptList(); } args.Add(index); return(new DekiScriptUri(uri.Value, args)); } case DekiScriptType.STR: { DekiScriptString text = (DekiScriptString)prefix; // coerce the index type to NUM double?value = index.AsNumber(); if (value == null) { throw new DekiScriptBadTypeException(expr.Location, index.ScriptType, new[] { DekiScriptType.NUM }); } // retrieve character at given index position int position = (int)value; if ((position < 0) || (position >= text.Value.Length)) { // index is out of bounds, return nil return(DekiScriptNil.Value); } return(DekiScriptExpression.Constant(text.Value[position].ToString())); } case DekiScriptType.XML: { string path = index.AsString(); if (path == null) { throw new DekiScriptBadTypeException(expr.Location, index.ScriptType, new[] { DekiScriptType.STR }); } XDoc doc = ((DekiScriptXml)prefix).Value[path]; if (doc.HasName("html")) { doc = DekiScriptLibrary.CleanseHtmlDocument(doc); } return(new DekiScriptXml(doc)); } case DekiScriptType.NIL: return(DekiScriptNil.Value); } throw new DekiScriptBadTypeException(expr.Location, prefix.ScriptType, new[] { DekiScriptType.MAP, DekiScriptType.LIST, DekiScriptType.XML, DekiScriptType.STR, DekiScriptType.URI }); }
public DekiScriptOutputBuffer.Range Visit(DekiScriptAccess expr, DekiScriptExpressionEvaluationState state) { return(state.Push(Evaluate(expr, state, true))); }
public DekiScriptLiteral Visit(DekiScriptAccess expr, DekiScriptEnv env) { return(Evaluate(expr, env, true)); }