示例#1
0
 private DekiScriptExpression TryCatch(DekiScriptExpression expr, bool scripted)
 {
     if (scripted)
     {
         return(DekiScriptExpression.ReturnScope(Location, expr));
     }
     return(expr);
 }
示例#2
0
        private DekiScriptInvocationTargetDescriptor ConvertFunction(XDoc function)
        {
            string functionName = function["name"].AsText;

            if (string.IsNullOrEmpty(functionName))
            {
                _log.WarnFormat("function without name in script {0}; skipping function definition", _manifestUri);
                return(null);
            }

            // determine function access level
            DreamAccess access;

            switch (function["access"].AsText ?? "public")
            {
            case "private":
                access = DreamAccess.Private;
                break;

            case "internal":
                access = DreamAccess.Internal;
                break;

            case "public":
                access = DreamAccess.Public;
                break;

            default:
                _log.WarnFormat("unrecognized access level '{0}' for function {1} in script {2}; defaulting to public", function["access"].AsText, functionName, _manifestUri);
                access = DreamAccess.Public;
                break;
            }

            // convert parameters
            List <DekiScriptParameter> parameters = new List <DekiScriptParameter>();

            foreach (XDoc param in function["param"])
            {
                string paramName = param["@name"].AsText;

                // determine if parameter has a default value
                string            paramDefault           = param["@default"].AsText;
                DekiScriptLiteral paramDefaultExpression = DekiScriptNil.Value;
                bool paramOptional = false;
                if (paramDefault != null)
                {
                    paramOptional = true;
                    try {
                        paramDefaultExpression = ScriptRuntime.Evaluate(DekiScriptParser.Parse(Location.Start, paramDefault), DekiScriptEvalMode.Evaluate, ScriptRuntime.CreateEnv());
                    } catch (Exception e) {
                        _log.ErrorExceptionFormat(e, "invalid default value for parameter {0} in function {1} in script {2}; skipping function definition", paramName, functionName, _manifestUri);
                        return(null);
                    }
                }
                else
                {
                    paramOptional = (param["@optional"].AsText == "true");
                }

                // determine parameter type
                string         paramType = param["@type"].AsText ?? "any";
                DekiScriptType paramScriptType;
                if (!SysUtil.TryParseEnum(paramType, out paramScriptType))
                {
                    _log.WarnFormat("unrecognized param type '{0}' for parameter {1} in function {2} in script {3}; defaulting to any", paramType, paramName, functionName, _manifestUri);
                    paramScriptType = DekiScriptType.ANY;
                }

                // add parameter
                parameters.Add(new DekiScriptParameter(paramName, paramScriptType, paramOptional, param.Contents, typeof(object), paramDefaultExpression));
            }
            var parameterArray = parameters.ToArray();

            // determine function body
            XDoc   ret  = function["return"];
            string src  = ret["@src"].AsText;
            string type = ret["@type"].AsText;
            DekiScriptExpression expression;

            if (!string.IsNullOrEmpty(src))
            {
                // 'src' attribute is set, load the script from it
                XDoc script;
                if (_manifestUri != null)
                {
                    // check if uri is relative
                    XUri scriptUri = XUri.TryParse(src) ?? _manifestUri.AtPath(src);
                    script = Plug.New(scriptUri).Get().ToDocument();
                }
                else
                {
                    // check if filename is relative
                    if (!Path.IsPathRooted(src))
                    {
                        src = Path.Combine(_resourcesPath, src);
                    }
                    script = XDocFactory.LoadFrom(src, MimeType.XML);
                }
                expression = DekiScriptParser.Parse(script);
                type       = type ?? "xml";
            }
            else if (!ret["html"].IsEmpty)
            {
                // <return> element contains a <html> node; parse it as a script
                expression = DekiScriptParser.Parse(ret["html"]);
                type       = type ?? "xml";
            }
            else if (!ret.IsEmpty)
            {
                // <return> element contains something else; use the text contents as deki-script expression
                var location = new Location(string.Format("/function[name={0}]/return", functionName));
                expression = DekiScriptParser.Parse(location, function["return"].AsText ?? string.Empty);
                expression = DekiScriptExpression.ReturnScope(location, expression);
                type       = type ?? "any";
            }
            else
            {
                _log.WarnFormat("function {0} has no body in script {1}; skipping function definition", functionName, _manifestUri);
                return(null);
            }

            // determine return type
            DekiScriptType returnScriptType;

            if (!SysUtil.TryParseEnum(type, out returnScriptType))
            {
                _log.WarnFormat("unrecognized return type '{0}' for function {1} in script {2}; defaulting to any", type, functionName, _manifestUri);
                returnScriptType = DekiScriptType.ANY;
            }

            // create function descriptor
            var    target      = new DekiScriptScriptFunctionInvocationTarget(access, parameterArray, expression, _commonEnv, returnScriptType);
            string description = function["description"].AsText;
            string transform   = function["@transform"].AsText;

            return(new DekiScriptInvocationTargetDescriptor(access, false, false, functionName, parameterArray, returnScriptType, description, transform, target));
        }