PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/System.Xronos/Builtins/SpecialMacros.SyntaxQuoteReader.cs

https://bitbucket.org/stefanrusek/xronos
C# | 222 lines | 173 code | 26 blank | 23 comment | 32 complexity | ea25f3fb7dbe087dd886367facee92d0 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) 2008 Stefan Rusek and Benjamin Pollack
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. *
  23. * ***************************************************************************/
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Linq;
  27. using System.Text;
  28. using System.Xronos.Language;
  29. using System.Text.RegularExpressions;
  30. namespace System.Xronos.Builtins
  31. {
  32. public sealed partial class SpecialMacros
  33. {
  34. static int c = 100;
  35. abstract class UnquoteBox : XronosObject
  36. {
  37. public object Value { get; set; }
  38. public UnquoteBox(IPersistentMap meta) : base(meta) { }
  39. }
  40. class Unquote : UnquoteBox
  41. {
  42. public Unquote(IPersistentMap meta) : base(meta) { }
  43. public override XronosObject withMeta(IPersistentMap meta)
  44. {
  45. return new Unquote(meta) { Value = Value };
  46. }
  47. }
  48. class UnquoteSplicing : UnquoteBox
  49. {
  50. public UnquoteSplicing(IPersistentMap meta) : base(meta) { }
  51. public override XronosObject withMeta(IPersistentMap meta)
  52. {
  53. return new UnquoteSplicing(meta) { Value = Value };
  54. }
  55. }
  56. class UnquoteReader : ReaderBase
  57. {
  58. protected override object Read(Reader reader, char c)
  59. {
  60. reader.Advance();
  61. UnquoteBox box;
  62. if (reader.Peek() == '@')
  63. box = new UnquoteSplicing(null) {Value = reader.Advance().InternalRead(false, null)};
  64. else
  65. box = new Unquote(null) { Value = reader.InternalRead(false, null) };
  66. return box;
  67. }
  68. }
  69. internal class SyntaxQuoteReader : ReaderBase
  70. {
  71. object nullObject = new object();
  72. protected override object Read(Reader reader, char c)
  73. {
  74. reader.Advance();
  75. var form = Expand(new Dictionary<Symbol,Symbol>(), reader.InternalRead(false, null));
  76. return form;
  77. }
  78. private object Expand(Dictionary<Symbol,Symbol> gensyms, object form)
  79. {
  80. object ret = null;
  81. if (form is IPersistentCollection || form is ISequence)
  82. ret = ExpandCollection(gensyms, form);
  83. else
  84. ret = ExpandNonCollection(gensyms, form);
  85. var obj = ret as XronosObject;
  86. if (obj != null && obj.meta() != null)
  87. {
  88. var newMeta = obj.meta().without(RT.Line);
  89. if (newMeta.count() > 0)
  90. ret = obj.withMeta(newMeta);
  91. }
  92. return ret;
  93. }
  94. private object ExpandCollection(Dictionary<Symbol, Symbol> gensyms, object form)
  95. {
  96. Symbol action;
  97. ISequence list;
  98. if (form is IPersistentList)
  99. {
  100. action = Symbol.Intern("xronos", "list");
  101. list = ((ISequential)form).seq();
  102. }
  103. else if (form is IPersistentMap)
  104. {
  105. action = Symbol.Intern("xronos", "hashmap");
  106. list = FlattenMap((IPersistentMap)form);
  107. }
  108. else if (form is IPersistentVector)
  109. {
  110. action = Symbol.Intern("xronos", "vector");
  111. list = ((ISequential)form).seq();
  112. }
  113. else if (form is IPersistentSet)
  114. {
  115. action = Symbol.Intern("xronos", "hashset");
  116. list = ((IPersistentCollection)form).seq();
  117. }
  118. else if (form is ISequence)
  119. {
  120. return RT.Cons(Symbol.Intern("xronos", "concat"), ExpandSequence(gensyms, RT.seq(form)));
  121. }
  122. else
  123. throw new NotSupportedException("Unknown Collection type");
  124. return RT.List(Symbol.Intern("xronos", "apply"), action, RT.Cons(Symbol.Intern("xronos", "concat"), ExpandSequence(gensyms, list)));
  125. }
  126. internal static ISequence FlattenMap(IPersistentMap form)
  127. {
  128. IPersistentVector ret = PersistentVector.Empty;
  129. for (ISequence it = form.seq(); it != null; it = it.rest())
  130. {
  131. var entry = (IMapEntry)it.first();
  132. ret = ret.cons(entry.key()).cons(entry.val());
  133. }
  134. return ((ISequential)ret).seq();
  135. }
  136. private ISequence ExpandSequence(Dictionary<Symbol, Symbol> gensyms, ISequence seq)
  137. {
  138. IPersistentVector ret = PersistentVector.Empty;
  139. for (ISequence it = seq; it != null; it = it.rest())
  140. {
  141. object o = it.first();
  142. var unq = o as UnquoteBox;
  143. var wrapInList = !(o is UnquoteSplicing);
  144. if (unq != null)
  145. {
  146. o = unq.Value;
  147. var meta = unq.meta();
  148. if (meta != null)
  149. o = RT.List(Symbol.Intern("xronos", "with-meta"), o, RT.List(Quote, meta));
  150. }
  151. else
  152. o = Expand(gensyms, o);
  153. if (wrapInList)
  154. o = RT.List(Symbol.Intern("xronos", "list"), o);
  155. ret = ret.cons(o);
  156. }
  157. return ((ISequential)ret).seq();
  158. }
  159. private object ExpandNonCollection(Dictionary<Symbol, Symbol> gensyms, object form)
  160. {
  161. object ret;
  162. Type t = (form ?? nullObject).GetType();
  163. switch (t.FullName)
  164. {
  165. case "System.Xronos.Language.Symbol":
  166. {
  167. var sym = (Symbol)form;
  168. if (sym.Namespace == null && sym.Name.EndsWith("#"))
  169. form = ExpandGenSym(gensyms, sym);
  170. }
  171. goto default;
  172. case "System.Xronos.Language.Keyword":
  173. case "System.Int16":
  174. case "System.Int32":
  175. case "System.Int64":
  176. case "System.Single":
  177. case "System.Double":
  178. case "System.String":
  179. ret = form;
  180. break;
  181. default:
  182. ret = RT.List(Quote, form);
  183. break;
  184. }
  185. return ret;
  186. }
  187. private object ExpandGenSym(Dictionary<Symbol,Symbol> gensyms, Symbol sym)
  188. {
  189. Symbol ret;
  190. if (!gensyms.TryGetValue(sym, out ret))
  191. gensyms[sym] = ret = Symbol.Intern("__GENSYM_" + (c++) + "_" + sym.Name.Substring(0, sym.Name.Length - 1));
  192. return ret;
  193. }
  194. }
  195. }
  196. }