/System.Xronos/Builtins/SpecialMacros.SyntaxQuoteReader.cs
C# | 222 lines | 173 code | 26 blank | 23 comment | 32 complexity | ea25f3fb7dbe087dd886367facee92d0 MD5 | raw file
- /* ****************************************************************************
- *
- * Copyright (c) 2008 Stefan Rusek and Benjamin Pollack
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * ***************************************************************************/
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Xronos.Language;
- using System.Text.RegularExpressions;
-
- namespace System.Xronos.Builtins
- {
- public sealed partial class SpecialMacros
- {
- static int c = 100;
- abstract class UnquoteBox : XronosObject
- {
- public object Value { get; set; }
- public UnquoteBox(IPersistentMap meta) : base(meta) { }
- }
- class Unquote : UnquoteBox
- {
- public Unquote(IPersistentMap meta) : base(meta) { }
-
- public override XronosObject withMeta(IPersistentMap meta)
- {
- return new Unquote(meta) { Value = Value };
- }
- }
- class UnquoteSplicing : UnquoteBox
- {
- public UnquoteSplicing(IPersistentMap meta) : base(meta) { }
-
- public override XronosObject withMeta(IPersistentMap meta)
- {
- return new UnquoteSplicing(meta) { Value = Value };
- }
- }
-
- class UnquoteReader : ReaderBase
- {
- protected override object Read(Reader reader, char c)
- {
- reader.Advance();
-
- UnquoteBox box;
- if (reader.Peek() == '@')
- box = new UnquoteSplicing(null) {Value = reader.Advance().InternalRead(false, null)};
- else
- box = new Unquote(null) { Value = reader.InternalRead(false, null) };
-
- return box;
- }
- }
-
- internal class SyntaxQuoteReader : ReaderBase
- {
- object nullObject = new object();
-
- protected override object Read(Reader reader, char c)
- {
- reader.Advance();
- var form = Expand(new Dictionary<Symbol,Symbol>(), reader.InternalRead(false, null));
-
- return form;
- }
-
- private object Expand(Dictionary<Symbol,Symbol> gensyms, object form)
- {
- object ret = null;
-
- if (form is IPersistentCollection || form is ISequence)
- ret = ExpandCollection(gensyms, form);
- else
- ret = ExpandNonCollection(gensyms, form);
-
- var obj = ret as XronosObject;
- if (obj != null && obj.meta() != null)
- {
- var newMeta = obj.meta().without(RT.Line);
- if (newMeta.count() > 0)
- ret = obj.withMeta(newMeta);
- }
- return ret;
- }
-
- private object ExpandCollection(Dictionary<Symbol, Symbol> gensyms, object form)
- {
- Symbol action;
- ISequence list;
- if (form is IPersistentList)
- {
- action = Symbol.Intern("xronos", "list");
- list = ((ISequential)form).seq();
- }
- else if (form is IPersistentMap)
- {
- action = Symbol.Intern("xronos", "hashmap");
- list = FlattenMap((IPersistentMap)form);
- }
- else if (form is IPersistentVector)
- {
- action = Symbol.Intern("xronos", "vector");
- list = ((ISequential)form).seq();
- }
- else if (form is IPersistentSet)
- {
- action = Symbol.Intern("xronos", "hashset");
- list = ((IPersistentCollection)form).seq();
- }
- else if (form is ISequence)
- {
- return RT.Cons(Symbol.Intern("xronos", "concat"), ExpandSequence(gensyms, RT.seq(form)));
- }
- else
- throw new NotSupportedException("Unknown Collection type");
-
- return RT.List(Symbol.Intern("xronos", "apply"), action, RT.Cons(Symbol.Intern("xronos", "concat"), ExpandSequence(gensyms, list)));
- }
-
- internal static ISequence FlattenMap(IPersistentMap form)
- {
- IPersistentVector ret = PersistentVector.Empty;
- for (ISequence it = form.seq(); it != null; it = it.rest())
- {
- var entry = (IMapEntry)it.first();
- ret = ret.cons(entry.key()).cons(entry.val());
- }
- return ((ISequential)ret).seq();
- }
-
- private ISequence ExpandSequence(Dictionary<Symbol, Symbol> gensyms, ISequence seq)
- {
- IPersistentVector ret = PersistentVector.Empty;
- for (ISequence it = seq; it != null; it = it.rest())
- {
- object o = it.first();
-
- var unq = o as UnquoteBox;
- var wrapInList = !(o is UnquoteSplicing);
- if (unq != null)
- {
- o = unq.Value;
-
- var meta = unq.meta();
- if (meta != null)
- o = RT.List(Symbol.Intern("xronos", "with-meta"), o, RT.List(Quote, meta));
- }
- else
- o = Expand(gensyms, o);
-
- if (wrapInList)
- o = RT.List(Symbol.Intern("xronos", "list"), o);
-
- ret = ret.cons(o);
- }
- return ((ISequential)ret).seq();
- }
-
- private object ExpandNonCollection(Dictionary<Symbol, Symbol> gensyms, object form)
- {
- object ret;
- Type t = (form ?? nullObject).GetType();
-
- switch (t.FullName)
- {
- case "System.Xronos.Language.Symbol":
- {
- var sym = (Symbol)form;
- if (sym.Namespace == null && sym.Name.EndsWith("#"))
- form = ExpandGenSym(gensyms, sym);
- }
- goto default;
-
- case "System.Xronos.Language.Keyword":
- case "System.Int16":
- case "System.Int32":
- case "System.Int64":
- case "System.Single":
- case "System.Double":
- case "System.String":
- ret = form;
- break;
-
- default:
- ret = RT.List(Quote, form);
- break;
- }
- return ret;
- }
-
- private object ExpandGenSym(Dictionary<Symbol,Symbol> gensyms, Symbol sym)
- {
- Symbol ret;
- if (!gensyms.TryGetValue(sym, out ret))
- gensyms[sym] = ret = Symbol.Intern("__GENSYM_" + (c++) + "_" + sym.Name.Substring(0, sym.Name.Length - 1));
-
- return ret;
- }
- }
- }
- }