public DekiScriptLiteral this[DekiScriptLiteral index] { get { if (index == null) { throw new ArgumentNullException("index"); } if ((index.ScriptType == DekiScriptType.NUM) || (index.ScriptType == DekiScriptType.STR)) { return(this[SysUtil.ChangeType <string>(index.NativeValue)]); } else { throw new DekiScriptBadTypeException(Location.None, index.ScriptType, new[] { DekiScriptType.NUM, DekiScriptType.STR }); } } set { if (index == null) { throw new ArgumentNullException("index"); } if ((index.ScriptType == DekiScriptType.NUM) || (index.ScriptType == DekiScriptType.STR)) { this[SysUtil.ChangeType <string>(index.NativeValue)] = value; } else { throw new DekiScriptBadTypeException(Location.None, index.ScriptType, new[] { DekiScriptType.NUM, DekiScriptType.STR }); } } }
//--- Extension Methods --- public static StringBuilder AppendLiteral(this StringBuilder builder, DekiScriptLiteral literal) { if(literal is DekiScriptString) { builder.Append(((DekiScriptString)literal).Value); } else { builder.Append(literal.ToString()); } return builder; }
//--- Methods --- public virtual DekiScriptLiteral Invoke(DekiScriptRuntime runtime, DekiScriptLiteral args) { if(args is DekiScriptList) { return InvokeList(runtime, (DekiScriptList)args); } else if(args is DekiScriptMap) { return InvokeMap(runtime, (DekiScriptMap)args); } else { throw new DekiScriptBadTypeException(Location.None, args.ScriptType, new[] { DekiScriptType.MAP, DekiScriptType.LIST }); } }
//--- Class Methods --- private static void XmlRpcLiteralRecurse(XDoc xdoc, DekiScriptLiteral value, bool isArgumentList) { if(!isArgumentList) { xdoc.Start("value"); } switch(value.ScriptType) { case DekiScriptType.BOOL: xdoc.Elem("boolean", ((DekiScriptBool)value).Value ? "1" : "0"); break; case DekiScriptType.NUM: xdoc.Elem("double", ((DekiScriptNumber)value).Value); break; case DekiScriptType.STR: xdoc.Elem("string", ((DekiScriptString)value).Value); // in order to work with php, this may need to be encoded break; case DekiScriptType.NIL: xdoc.Elem("nil"); break; case DekiScriptType.URI: xdoc.Start("string").Attr("type", "uri").End(); break; case DekiScriptType.XML: xdoc.Start("string").Attr("type", "xml").Value(value.NativeValue.ToString()).End(); break; case DekiScriptType.LIST: xdoc.Start(isArgumentList ? "params" : "array"); if(!isArgumentList) xdoc.Start("data"); foreach(DekiScriptLiteral entry in ((DekiScriptList)value).Value) { if(isArgumentList) { xdoc.Start("param"); XmlRpcLiteralRecurse(xdoc, entry, false); xdoc.End(); } else { XmlRpcLiteralRecurse(xdoc, entry, false); } } if(!isArgumentList) xdoc.End(); xdoc.End(); break; case DekiScriptType.MAP: xdoc.Start("struct"); foreach(KeyValuePair<string, DekiScriptLiteral> entry in ((DekiScriptMap)value).Value) { xdoc.Start("member"); xdoc.Elem("name", entry.Key); XmlRpcLiteralRecurse(xdoc, entry.Value, false); xdoc.End(); } xdoc.End(); break; default: throw new ShouldNeverHappenException("unkwown type"); } if(!isArgumentList) xdoc.End(); return; }
//--- Methods --- public DekiScriptList Add(DekiScriptLiteral value) { if (value == null) { throw new ArgumentNullException("value"); } Value.Add(value); return(this); }
public DekiScriptMap AddAt(string path, DekiScriptLiteral value) { if (path == null) { throw new ArgumentNullException("path"); } if (value == null) { throw new ArgumentNullException("value"); } return(AddAt(path.Split('.'), value)); }
public bool TryGetValue(string name, out DekiScriptLiteral value) { if (!_value.TryGetValue(name, out value)) { if (Outer != null) { return(Outer.TryGetValue(name, out value)); } value = DekiScriptNil.Value; return(false); } return(true); }
//--- Constructors --- internal DekiScriptUri(XUri value, DekiScriptLiteral args) { if (value == null) { throw new ArgumentNullException("value"); } if (args == null) { throw new ArgumentNullException("args"); } Value = value; Arguments = args; }
public bool TryGetValue(DekiScriptLiteral index, out DekiScriptLiteral value) { if (index == null) { throw new ArgumentNullException("index"); } if ((index.ScriptType == DekiScriptType.NUM) || (index.ScriptType == DekiScriptType.STR)) { return(TryGetValue(SysUtil.ChangeType <string>(index.NativeValue), out value)); } else { throw new DekiScriptBadTypeException(Location.None, index.ScriptType, new[] { DekiScriptType.NUM, DekiScriptType.STR }); } }
public DekiScriptLiteral this[DekiScriptLiteral index] { get { if (index == null) { return(DekiScriptNil.Value); } if (index.ScriptType == DekiScriptType.NUM) { return(this[SysUtil.ChangeType <int>(index.NativeValue)]); } else { return(DekiScriptNil.Value); } } }
public DekiScriptMap AddAt(string[] keys, DekiScriptLiteral value, bool ignoreOnError) { if (ArrayUtil.IsNullOrEmpty(keys)) { throw new ArgumentNullException("keys"); } if (value == null) { throw new ArgumentNullException("value"); } // loop over all keys, except last, to get to the last map string key; DekiScriptMap current = this; for (int i = 0; i < keys.Length - 1; ++i) { if (keys[i] == null) { if (ignoreOnError) { return(this); } throw new ArgumentException(string.Format("keys[{0}] is null", i)); } key = keys[i]; DekiScriptLiteral next = current[key]; if (next.ScriptType == DekiScriptType.NIL) { next = new DekiScriptMap(); current.Add(key, next); } else if (next.ScriptType != DekiScriptType.MAP) { if (ignoreOnError) { return(this); } throw new Exception(string.Format("entry at '{0}' is not a map", string.Join(".", keys, 0, i + 1))); } current = (DekiScriptMap)next; } // add new item using the final key current.Add(keys[keys.Length - 1], value); return(this); }
public static DekiScriptLiteral Constant(XUri value, DekiScriptLiteral[] items) { DekiScriptLiteral args = DekiScriptNil.Value; if (!ArrayUtil.IsNullOrEmpty(items)) { args = List(items); } else { // BUGBUGBUG (steveb): we should NOT do execution when building the model! if (value.Fragment != null) { DekiScriptExpression expr = DekiScriptParser.TryParse(value.Fragment) ?? DekiScriptNil.Value; args = EvalRuntime.Evaluate(expr, DekiScriptEvalMode.EvaluateSafeMode, new DekiScriptEnv()); } } if ((args.ScriptType != DekiScriptType.NIL) && (args.ScriptType != DekiScriptType.LIST) && (args.ScriptType != DekiScriptType.MAP)) { throw new DekiScriptBadTypeException(Location.None, args.ScriptType, new[] { DekiScriptType.NIL, DekiScriptType.LIST, DekiScriptType.MAP }); } return(new DekiScriptUri(value.WithoutFragment(), args)); }
public override DekiScriptLiteral Convert(DekiScriptType type) { switch (type) { case DekiScriptType.ANY: case DekiScriptType.XML: return(this); case DekiScriptType.BOOL: case DekiScriptType.NUM: case DekiScriptType.STR: case DekiScriptType.URI: { string value = AsString(); if (value != null) { DekiScriptLiteral str = Constant(value); return(str.Convert(type)); } break; } } throw new DekiScriptInvalidCastException(Location, ScriptType, type); }
//--- Methods --- public DekiScriptMap Add(string key, DekiScriptLiteral value) { if (key == null) { throw new ArgumentNullException("key"); } // check if colleciton is readonly if (_readonly) { throw new ReadOnlyException(string.Format("map is read-only (attempted to add key '{0}')", key)); } // update value if (value == null) { _value.Remove(key); } else { _value[key] = value; } return(this); }
public static DekiScriptLiteral NotEqual(DekiScriptLiteral left, DekiScriptLiteral right) { if (DekiScriptLiteral.CoerceValuesToSameType(ref left, ref right)) { switch (left.ScriptType) { case DekiScriptType.NIL: return(DekiScriptBool.False); case DekiScriptType.BOOL: return(Constant(left.AsBool() != right.AsBool())); case DekiScriptType.NUM: return(Constant(left.AsNumber() != right.AsNumber())); case DekiScriptType.STR: return(Constant(!StringUtil.EqualsInvariant(left.AsString(), right.AsString()))); default: return(Constant(!object.ReferenceEquals(left, right))); } } return(DekiScriptBool.True); }
public static DekiScriptLiteral IdentityNotEqual(DekiScriptLiteral left, DekiScriptLiteral right) { if (left.ScriptType == right.ScriptType) { switch (left.ScriptType) { case DekiScriptType.NIL: return(DekiScriptBool.False); case DekiScriptType.BOOL: return(Constant(left.AsBool() != right.AsBool())); case DekiScriptType.NUM: return(Constant(left.AsNumber() != right.AsNumber())); case DekiScriptType.STR: return(Constant(!StringUtil.EqualsInvariant(left.AsString(), right.AsString()))); default: return(Constant(!ReferenceEquals(left, right))); } } return(DekiScriptBool.True); }
private void AddText(XmlNode context, DekiScriptLiteral literal) { if(context == null) { ConvertStateToHtml(null); } // TODO (steveb): this is just plain retarded; why do we need to distinguish between string and non-string?!? if(literal is DekiScriptString) { (context ?? _body).AppendChild(_document.CreateTextNode(((DekiScriptString)literal).Value)); } else { (context ?? _body).AppendChild(_document.CreateTextNode(literal.ToString())); } }
//--- Methods --- public DekiScriptLiteral Convert(DekiScriptLiteral value) { try { return value.Convert(ScriptType); } catch(DekiScriptInvalidCastException) { throw new DekiScriptInvalidParameterCastException(Location.None, this, value.ScriptType); } }
public Range Push(DekiScriptLiteral literal) { if(literal.IsNil) { return Range.Empty; } // append element int start = _buffer.Count; CheckBufferLimits(); _buffer.Add(literal); return new Range(start, _buffer.Count); }
internal void ReplaceNodeWithValue(XmlNode node, DekiScriptLiteral value) { XmlNode parent = node.ParentNode; InsertValueBeforeNode(parent, node, value); parent.RemoveChild(node); }
public virtual DekiScriptLiteral Invoke(Location location, XUri uri, DekiScriptLiteral args, DekiScriptEnv env) { var sw = Stopwatch.StartNew(); DekiScriptInvocationTargetDescriptor descriptor; var target = _functions.TryGetValue(uri, out descriptor) ? descriptor.Target : FindTarget(uri); try { // invoke function directly return target.Invoke(this, args); } catch(Exception e) { throw UnwrapAsyncException(uri, e).Rethrow(); } finally { sw.Stop(); bool property = (uri.LastSegment ?? string.Empty).StartsWithInvariant("$"); env.AddFunctionProfile(location, (descriptor != null) ? (property ? "$" : "") + descriptor.Name : uri.ToString(), sw.Elapsed); } }
//--- Contructors --- public DekiScriptParameter(string name, DekiScriptType type, bool optional, string hint) { if(string.IsNullOrEmpty(name)) { throw new NullReferenceException("name"); } this.Name = name; this.ScriptType = type; this.Optional = optional; this.Hint = hint; this.NativeType = typeof(object); this.Default = DekiScriptNil.Value; }
//--- Class Methods --- public static bool IsProperty(DekiScriptLiteral value) { if(value.ScriptType == DekiScriptType.URI) { return (((DekiScriptUri)value).Value.LastSegment ?? string.Empty).StartsWithInvariant("$"); } return false; }
//--- Class Methods --- public static XDoc Include(string path, string section, bool showTitle, int? adjustHeading, DekiScriptLiteral args, int revision, bool followRedirects, bool returnEmptyDocIfNotFound, bool createAnchor) { var resources = DekiContext.Current.Resources; // retrieve the page requested Title titleToInclude = Title.FromUriPath(path); PageBE pageToInclude = PageBL.GetPageByTitle(titleToInclude); if(followRedirects) { pageToInclude = PageBL.ResolveRedirects(pageToInclude); } // If the page was not found, create a link to the page placeholder if(pageToInclude.ID == 0) { return returnEmptyDocIfNotFound ? XDoc.Empty : new XDoc("html").Start("body").Start("a").Attr("href", path).Value(titleToInclude.AsUserFriendlyName()).End().End(); } if(!PermissionsBL.IsUserAllowed(DekiContext.Current.User, pageToInclude, Permissions.READ)) { return new XDoc("html").Start("body").Value(resources.Localize(DekiResources.RESTRICT_MESSAGE())).End(); } // load old revision of page if(revision != 0) { PageBL.ResolvePageRev(pageToInclude, revision.ToString()); } // parse the page ParserResult result = Parse(pageToInclude, pageToInclude.ContentType, pageToInclude.Language, pageToInclude.GetText(DbUtils.CurrentSession), ParserMode.VIEW, true, -1, args, null); // if requested, extract the specified section XDoc doc; if(section != null) { XmlNode startNode, endNode; FindSection(result.MainBody, section, out startNode, out endNode); XDoc body = ExtractSection(false, startNode, endNode); // If the section was not found, create a link to the page whose section is missing if(null == startNode) { if(returnEmptyDocIfNotFound) { return XDoc.Empty; } body = body.Start("a").Attr("href", path).Attr("rel", "internal").Value(titleToInclude.AsUserFriendlyName()).End(); } else if(adjustHeading.HasValue) { // header needs to be adjusted int current; if(int.TryParse(startNode.LocalName.Substring(1), out current)) { if(showTitle) { body.AddNodesInFront(new XDoc("body").Add(result.MainBody[startNode])); } RelabelHeadings(body, adjustHeading.Value - current); } } doc = new XDoc("html").Add(result.Head).Add(body).Add(result.Tail); } else { doc = new XDoc("html").Add(result.Head); // check if header needs to be adjusted if(adjustHeading.HasValue) { if(showTitle) { result.MainBody.AddNodesInFront(new XDoc("body").Elem("h1", pageToInclude.CustomTitle ?? pageToInclude.Title.AsUserFriendlyName())); } RelabelHeadings(result.MainBody, adjustHeading.Value - 1); } // add optional anchor if(createAnchor) { result.MainBody.AddNodesInFront(new XDoc("body").Start("span").Attr("pagelink", DekiContext.Current.UiUri.AtPath(pageToInclude.Title.AsUiUriPath())).Attr("id", "s" + pageToInclude.ID).End()); } doc.AddAll(result.Bodies).Add(result.Tail); } // replace all <span id="page.toc" /> place holders if(!pageToInclude.Title.IsTemplate) { var toc = ProcessPageHeadings(doc); XDoc tocDiv = null; foreach(XDoc pageToc in doc["body//span[@id='page.toc']"]) { if(tocDiv == null) { tocDiv = new XDoc("div").Attr("class", "wiki-toc").AddNodes(toc); } pageToc.Replace(TruncateTocDepth(tocDiv, pageToc["@depth"].AsInt)); } } return doc; }
public static ParserResult Parse(PageBE page, string contentType, string language, string content, ParserMode mode, bool isInclude, int section, DekiScriptLiteral args, Title relToTitle) { XDoc xhtml = CreateParserDocument(page, contentType, language, content, mode); // check if we're interested only in a given section if(0 < section) { XDoc mainBody = xhtml[MAIN_BODY_XPATH]; XmlNode startNode, endNode; FindSection(mainBody, section, out startNode, out endNode); mainBody.Replace(ExtractSection(true, startNode, endNode)); } // process page contents ParserResult result = Parse(page, xhtml, mode, isInclude, args, relToTitle); // check if we need to append extra elements to document for editing if(mode == ParserMode.EDIT) { XDoc body = result.MainBody; if(!body.IsEmpty) { XmlNode last = body.AsXmlNode.LastChild; // check if last node is a <table> or <pre> element if(last != null) { if(last.NodeType == XmlNodeType.Element) { if(last.LocalName.EqualsInvariant("table") || last.LocalName.EqualsInvariant("pre")) { // add a <br /> element body.Elem("br"); } else if(last.LocalName.EqualsInvariant("h1") || last.LocalName.EqualsInvariant("h2") || last.LocalName.EqualsInvariant("h3") || last.LocalName.EqualsInvariant("h4") || last.LocalName.EqualsInvariant("h5") || last.LocalName.EqualsInvariant("h6") ) { // add a <br /> element body.Elem("br"); } } } else { // add a <br /> element body.Elem("br"); } } } else if(((mode == ParserMode.VIEW) || (mode == ParserMode.VIEW_NO_EXECUTE)) && isInclude) { XDoc body = result.MainBody; XmlNode para = null; foreach(XmlNode node in body.AsXmlNode.ChildNodes) { if((node.NodeType == XmlNodeType.Element) && node.Name.EqualsInvariant("p") && (para == null)) { // capture the first <p> node para = node; continue; } else if(node.NodeType == XmlNodeType.Whitespace) { // found a whitespace node; ignore it continue; } else if((node.NodeType == XmlNodeType.Text) && string.IsNullOrEmpty(node.Value.Trim())) { // found an empty text node; ignore it continue; } // found other content; don't strip anything para = null; break; } // check if a single paragraph was found; if so, remove the <p> tags, but keep the contents if(para != null) { body.RemoveNodes(); body.AddNodes(body[para]); } } return result; }
private static ParserResult Parse(PageBE page, XDoc result, ParserMode mode, bool isInclude, DekiScriptLiteral args, Title relToTitle) { Title redirectsToTitle = null; XUri redirectsToUri = null; bool hasScriptContent = false; List<Title> outboundLinks = null; List<Title> templates = null; List<string> tags = null; XDoc tableOfContents = null; if(ParserMode.RAW != mode) { // lookup the current parse state ParserState parseState = GetParseState(); string parseStateKey = GetParserCacheKey(page, mode); XDoc cachedResult = null; // if this page is included whithin another, check the state of the parse cache if(isInclude && parseState.ProcessedPages.TryGetValue(parseStateKey, out cachedResult)) { if(null == cachedResult) { if(mode == ParserMode.VIEW) { mode = ParserMode.VIEW_NO_EXECUTE; parseStateKey = GetParserCacheKey(page, mode); } else { throw new DekiXmlParserInfinitePageInclusionInvalidScriptException(); } } else { result = cachedResult; } } if(null == cachedResult) { // init environment for page processing PageBE basePage = page; if(page.Title.IsTemplate) { for(int i = parseState.ProcessingStack.Count - 1; i >= 0; --i) { // select the first non-template page if(!parseState.ProcessingStack[i].Title.IsTemplate) { basePage = parseState.ProcessingStack[i]; break; } } } // update the parse state to indicate the page is in the process of being parsed parseState.ProcessedPages[parseStateKey] = null; parseState.ProcessingStack.Add(page); // set current page in context DreamContext context = DreamContext.Current; PageBE prevBasePage = context.GetState<PageBE>("CurrentPage"); CultureInfo prevCulture = context.Culture; context.SetState("CurrentPage", basePage); context.Culture = HttpUtil.GetCultureInfoFromHeader(basePage.Language, context.Culture); // resolve the redirect if this page is marked as a redirect or new content is being processed if(page.IsRedirect || (ParserMode.SAVE == mode)) { object redirect = ProcessRedirect(result, mode); redirectsToTitle = redirect as Title; redirectsToUri = redirect as XUri; } if((null != redirectsToTitle) || (null != redirectsToUri)) { outboundLinks = new List<Title>(); if(null != redirectsToTitle) { outboundLinks.Add(redirectsToTitle); } } else { // check 'content-type' to determine if we need to convert if(DekiMimeType.DEKI_TEXT.EqualsInvariant(result["content/@type"].Contents)) { WikiConverter_TextToXml.Convert(result); result["content/@type"].ReplaceValue(DekiMimeType.DEKI_XML0702); } ProcessPage(page, result, mode, isInclude, basePage, args, relToTitle, out tableOfContents, out hasScriptContent, out outboundLinks, out templates, out tags); } // restore previous page context context.SetState("CurrentPage", prevBasePage); context.Culture = prevCulture; // update the parse state to indicate the page as been successfully parsed if(!page.Title.IsTemplate) { parseState.ProcessedPages[parseStateKey] = result; } else { parseState.ProcessedPages.Remove(parseStateKey); } parseState.ProcessingStack.RemoveAt(parseState.ProcessingStack.Count - 1); } } // add table of contents XDoc content = result["content"]; if((tableOfContents != null) && content["body[@target='toc']"].IsEmpty) { content.Start("body").Attr("target", "toc").AddNodes(tableOfContents); } // get content type string contentType = result["content/@type"].Contents; result["content/@type"].Remove(); // extract the parser results return new ParserResult( result["content"], contentType, redirectsToTitle, redirectsToUri, hasScriptContent, outboundLinks, templates, tags ); }
public DekiScriptMap AddAt(string[] keys, DekiScriptLiteral value) { return(AddAt(keys, value, true)); }
private static void ProcessPage(PageBE page, XDoc content, ParserMode mode, bool isInclude, PageBE basePage, DekiScriptLiteral args, Title relToTitle, out XDoc tableOfContents, out bool hasScriptContent, out List<Title> outboundLinks, out List<Title> templates, out List<string> tags) { DekiXmlParser parser = new DekiXmlParser(page, content, mode, isInclude, basePage, args, relToTitle); // 1) process structure of document parser.ProcessStructure(); tags = parser.ProcessTagsToBeInserted(); // 2) process edit sections parser.ProcessEditSections(); // 3) process links to attachments parser.ProcessAttachmentLinks(); // 4) process script content (variables and functions) hasScriptContent = parser.ProcessScripts(); // 5) process free-form external links parser.ProcessFreeLinks(); // 6) process internal/external links parser.ProcessLinks(out outboundLinks, out templates); // 7) process images parser.ProcessImages(); // 8) auto-number links parser.AutoNumberLinks(); // 9) process nowiki tags parser.ProcessNoWiki(); // 10) process words (banned & highlighted) parser.ProcessWords(); // 11) process headings tableOfContents = parser.ProcessHeadings(); // adjust content type if(mode == ParserMode.SAVE) { content["content/@type"].ReplaceValue(DekiMimeType.DEKI_XML0805); } else if(mode == ParserMode.EDIT) { content["content/@type"].ReplaceValue(DekiMimeType.DEKI_TEXT); } else if((mode == ParserMode.VIEW_NO_EXECUTE) || (mode == ParserMode.VIEW)) { content["content/@type"].ReplaceValue(DekiMimeType.HTML_TEXT); } }
//--- Constructors --- public DekiScriptReturnException(Location location, DekiScriptLiteral value) : base(location, "Unhandled 'return' statement") { if(value == null) { throw new ArgumentNullException("value"); } this.Value = value; }
public virtual DekiScriptLiteral EvaluateProperty(Location location, DekiScriptLiteral value, DekiScriptEnv env) { if(IsProperty(value)) { DekiScriptUri uri = (DekiScriptUri)value; try { value = Invoke(uri.Value, uri.Arguments.IsNil ? _emptyList : uri.Arguments, env); } catch(DekiScriptFatalException) { throw; } catch(Exception e) { var descriptor = ResolveRegisteredFunctionUri(uri.Value); throw new DekiScriptInvokeException(location, uri.Value, (descriptor != null) ? descriptor.Name : uri.Value.ToString(), e); } } return value; }
//--- Constructors --- private DekiXmlParser(PageBE page, XDoc content, ParserMode mode, bool isInclude, PageBE basePage, DekiScriptLiteral args, Title relToTitle) { this._page = page; this._content = content; this._mode = mode; this._isInclude = isInclude; this._basePage = basePage; this._args = args; this._relToTitle = relToTitle; }
public virtual DekiScriptLiteral Invoke(XUri uri, DekiScriptLiteral args, DekiScriptEnv env) { DekiScriptInvocationTargetDescriptor descriptor; var target = _functions.TryGetValue(uri, out descriptor) ? descriptor.Target : FindTarget(uri); // invoke function directly try { return target.Invoke(this, args); } catch(Exception e) { throw UnwrapAsyncException(uri, e).Rethrow(); } }
public static XDoc DekiScriptToXmlRpc(string function, DekiScriptLiteral arguments) { XDoc xdoc = new XDoc("methodCall"); xdoc.Elem("methodName", function); if(arguments.ScriptType.Equals(DekiScriptType.LIST)) { XmlRpcLiteralRecurse(xdoc, arguments, true); } else { xdoc.Start("params").Start("param"); XmlRpcLiteralRecurse(xdoc, arguments, false); xdoc.End().End(); } return xdoc; }
public DekiScriptParameter(string name, DekiScriptType type, bool optional, string hint, Type nativeType, DekiScriptLiteral @default) { if(string.IsNullOrEmpty(name)) { throw new NullReferenceException("name"); } if(nativeType == null) { throw new NullReferenceException("nativeType"); } if(@default == null) { throw new NullReferenceException("default"); } this.Name = name; this.ScriptType = type; this.Optional = optional; this.Hint = hint; this.NativeType = nativeType; this.Default = @default; }
public static bool CoerceValuesToSameType(ref DekiScriptLiteral left, ref DekiScriptLiteral right) { // weed out the trivial case where the literals cannot be converted switch (left.ScriptType) { case DekiScriptType.NIL: case DekiScriptType.URI: case DekiScriptType.LIST: case DekiScriptType.MAP: case DekiScriptType.XML: // we can't convert complex literals; only succeed if the types match return(left.ScriptType == right.ScriptType); } switch (right.ScriptType) { case DekiScriptType.NIL: case DekiScriptType.URI: case DekiScriptType.LIST: case DekiScriptType.MAP: case DekiScriptType.XML: // we can't convert complex literals; only succeed if the types match return(left.ScriptType == right.ScriptType); } // now determine what needs to be converted switch (left.ScriptType) { case DekiScriptType.BOOL: switch (right.ScriptType) { case DekiScriptType.BOOL: // nothing to do return(true); case DekiScriptType.NUM: // convert left value from bool to number left = Constant(left.AsNumber()); return(true); case DekiScriptType.STR: { // check if right string can be converted to bool; otherwise convert left bool to string bool?value = right.AsBool(); if (value == null) { left = Constant(left.AsString()); } else { right = Constant(value); } return(true); } } break; case DekiScriptType.NUM: switch (right.ScriptType) { case DekiScriptType.BOOL: // convert right value from bool to number right = Constant(right.AsNumber()); return(true); case DekiScriptType.NUM: // nothing to do return(true); case DekiScriptType.STR: { // check if right string can be converted to number; otherwise convert left number to string double?value = right.AsNumber(); if (value == null) { left = Constant(left.AsString()); } else { right = Constant(value); } return(true); } } break; case DekiScriptType.STR: switch (right.ScriptType) { case DekiScriptType.BOOL: { // check if left string can be converted to bool; otherwise convert right bool to string bool?value = left.AsBool(); if (value == null) { right = Constant(right.AsString()); } else { left = Constant(value); } return(true); } case DekiScriptType.NUM: { // check if left string can be converted to number; otherwise convert right number to string double?value = left.AsNumber(); if (value == null) { right = Constant(right.AsString()); } else { left = Constant(value); } return(true); } case DekiScriptType.STR: // nothing to do return(true); } break; } throw new InvalidOperationException(string.Format("invalid value pair: left = {0}, right = {1}", left.ScriptTypeName, right.ScriptTypeName)); }
public virtual void LogExceptionInOutput(DekiScriptLiteral error) { Log.Info("exception in dekiscript output: " + DekiScriptLibrary.JsonFormat(error.NativeValue)); }
public static bool CoerceValuesToSameType(ref DekiScriptLiteral left, ref DekiScriptLiteral right) { // weed out the trivial case where the literals cannot be converted switch(left.ScriptType) { case DekiScriptType.NIL: case DekiScriptType.URI: case DekiScriptType.LIST: case DekiScriptType.MAP: case DekiScriptType.XML: // we can't convert complex literals; only succeed if the types match return left.ScriptType == right.ScriptType; } switch(right.ScriptType) { case DekiScriptType.NIL: case DekiScriptType.URI: case DekiScriptType.LIST: case DekiScriptType.MAP: case DekiScriptType.XML: // we can't convert complex literals; only succeed if the types match return left.ScriptType == right.ScriptType; } // now determine what needs to be converted switch(left.ScriptType) { case DekiScriptType.BOOL: switch(right.ScriptType) { case DekiScriptType.BOOL: // nothing to do return true; case DekiScriptType.NUM: // convert left value from bool to number left = Constant(left.AsNumber()); return true; case DekiScriptType.STR: { // check if right string can be converted to bool; otherwise convert left bool to string bool? value = right.AsBool(); if(value == null) { left = Constant(left.AsString()); } else { right = Constant(value); } return true; } } break; case DekiScriptType.NUM: switch(right.ScriptType) { case DekiScriptType.BOOL: // convert right value from bool to number right = Constant(right.AsNumber()); return true; case DekiScriptType.NUM: // nothing to do return true; case DekiScriptType.STR: { // check if right string can be converted to number; otherwise convert left number to string double? value = right.AsNumber(); if(value == null) { left = Constant(left.AsString()); } else { right = Constant(value); } return true; } } break; case DekiScriptType.STR: switch(right.ScriptType) { case DekiScriptType.BOOL: { // check if left string can be converted to bool; otherwise convert right bool to string bool? value = left.AsBool(); if(value == null) { right = Constant(right.AsString()); } else { left = Constant(value); } return true; } case DekiScriptType.NUM: { // check if left string can be converted to number; otherwise convert right number to string double? value = left.AsNumber(); if(value == null) { right = Constant(right.AsString()); } else { left = Constant(value); } return true; } case DekiScriptType.STR: // nothing to do return true; } break; } throw new InvalidOperationException(string.Format("invalid value pair: left = {0}, right = {1}", left.ScriptTypeName, right.ScriptTypeName)); }
public DekiScriptOutputBuffer.Range Push(DekiScriptLiteral value) { return Buffer.Push(value); }
internal void InsertValueBeforeNode(XmlNode parent, XmlNode reference, DekiScriptLiteral value) { if((value is DekiScriptXml) || (value is DekiScriptUri)) { XDoc xml = value.AsEmbeddableXml(Mode == DekiScriptEvalMode.EvaluateSafeMode); if(xml.HasName("html")) { // TODO (steveb): merge XML namespaces // merge <head> and <tail> sections AddHeadElements(xml); AddTailElements(xml); // loop over body elements in response foreach(XDoc body in xml["body"]) { string target = body["@target"].AsText; string conflict = body["@conflict"].AsText ?? "ignore"; // check if the main body is targeted or something else if(string.IsNullOrEmpty(target)) { // append body nodes foreach(XmlNode node in body.AsXmlNode.ChildNodes) { parent.InsertBefore(parent.OwnerDocument.ImportNode(node, true), reference); } } else { // check if the targeted body already exists if(Bodies.ContainsKey(target) && !StringUtil.EqualsInvariant(conflict, "replace")) { if(StringUtil.EqualsInvariant(conflict, "append")) { // append nodes to existing body Bodies[target].Add(body.AsXmlNode); } } else { // create a new body element List<XmlNode> list = new List<XmlNode>(); list.Add(body.AsXmlNode); Bodies[target] = list; } } } } else if(!xml.IsEmpty) { // replace the current node with the entire document parent.InsertBefore(parent.OwnerDocument.ImportNode(xml.AsXmlNode, true), reference); } } else if(value is DekiScriptComplexLiteral) { // append text respresentation of value parent.InsertBefore(CreateTextNode(value.ToString()), reference); } else { // append value cast to text string text = value.AsString(); if(!string.IsNullOrEmpty(text)) { parent.InsertBefore(CreateTextNode(text), reference); } } }