PageRenderTime 39ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lisp/Sequence.cs

http://github.com/toshok/shelisp
C# | 193 lines | 154 code | 35 blank | 4 comment | 35 complexity | d4e278b1c1b9d8fe751cc3f0218fa657 MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace Shelisp {
  5. public abstract class Sequence : Object, IEnumerable<Shelisp.Object> {
  6. public abstract int Length { get; }
  7. public abstract IEnumerator<Shelisp.Object> GetEnumerator ();
  8. IEnumerator IEnumerable.GetEnumerator ()
  9. {
  10. return GetEnumerator();
  11. }
  12. public override bool LispEqual (Shelisp.Object other)
  13. {
  14. // is this right? can lists be equal to vectors if the elements are the same?
  15. if (other.GetType() != this.GetType()) {
  16. return false;
  17. }
  18. IEnumerator<Shelisp.Object> this_enum = this.GetEnumerator();
  19. IEnumerator<Shelisp.Object> other_enum = ((Sequence)other).GetEnumerator();
  20. while (this_enum.MoveNext()) {
  21. if (!other_enum.MoveNext())
  22. return false;
  23. if (!this_enum.Current.LispEqual (other_enum.Current))
  24. return false;
  25. }
  26. if (other_enum.MoveNext()) // there are more items left in other_enum
  27. return false;
  28. return true;
  29. }
  30. [LispBuiltin]
  31. public static Shelisp.Object Fsequencep(L l, Shelisp.Object o)
  32. {
  33. return (o is Sequence) ? L.Qt : L.Qnil;
  34. }
  35. [LispBuiltin]
  36. public static Shelisp.Object Felt(L l, Shelisp.Object seq, Shelisp.Object index)
  37. {
  38. if (L.Qnil.LispEq (seq))
  39. return L.Qnil;
  40. // XXX add type checks
  41. int idx = (int)(Number)index;
  42. foreach (var el in (Sequence)seq)
  43. if (idx-- == 0)
  44. return el;
  45. return L.Qnil;
  46. }
  47. [LispBuiltin]
  48. public static Shelisp.Object Fnth(L l, Shelisp.Object index, Shelisp.Object seq)
  49. {
  50. return Sequence.Felt (l, seq, index);
  51. }
  52. [LispBuiltin]
  53. public static Shelisp.Object Flength(L l, Shelisp.Object o)
  54. {
  55. if (L.NILP (o))
  56. return 0;
  57. if (!(o is Sequence))
  58. throw new Exception ("non-seq passed to length");
  59. Sequence seq = (Sequence)o;
  60. return seq.Length;
  61. }
  62. [LispBuiltin]
  63. public static Shelisp.Object Fcopy_sequence(L l, Shelisp.Object seq)
  64. {
  65. // XXX bad bad bad
  66. return seq;
  67. }
  68. [LispBuiltin]
  69. public static Shelisp.Object Fmapcar(L l, Shelisp.Object fun, Shelisp.Object seq)
  70. {
  71. if (L.NILP(seq))
  72. return L.Qnil;
  73. if (!(seq is Sequence))
  74. throw new WrongTypeArgumentException ("sequencep", seq);
  75. Sequence s = (Sequence)seq;
  76. List<Shelisp.Object> mapped = new List<Shelisp.Object>();
  77. foreach (var o in s) {
  78. var application = L.make_list (fun, new List (L.Qquote, new List (o, L.Qnil)));
  79. mapped.Add(application.Eval (l));
  80. }
  81. return new List (mapped.ToArray());
  82. }
  83. [LispBuiltin]
  84. public static Shelisp.Object Fmapc(L l, Shelisp.Object fun, Shelisp.Object seq)
  85. {
  86. if (L.Qnil.LispEq (seq))
  87. return L.Qnil;
  88. if (!(seq is Sequence))
  89. throw new WrongTypeArgumentException ("sequencep", seq);
  90. Sequence s = (Sequence)seq;
  91. foreach (var o in s)
  92. L.make_list (fun, new List (L.Qquote, new List (o, L.Qnil))).Eval (l);
  93. return seq;
  94. }
  95. [LispBuiltin]
  96. public static Shelisp.Object Fappend (L l, params Shelisp.Object[] sequences)
  97. {
  98. if (sequences.Length == 0)
  99. return L.Qnil;
  100. Shelisp.Object tail = sequences[sequences.Length - 1];
  101. for (int i = sequences.Length - 2; i >= 0; i --) {
  102. if (sequences[i] is Array) {
  103. Array arr = (Array)sequences[i];
  104. for (int j = arr.Length - 1; j >= 0; j --)
  105. tail = new List (arr[j], tail);
  106. }
  107. else if (sequences[i] is List) {
  108. Shelisp.List reversed = (Shelisp.List)Shelisp.List.reverse (sequences[i]);
  109. foreach (var el in reversed)
  110. tail = new List(el, tail);
  111. }
  112. }
  113. return tail;
  114. }
  115. [LispBuiltin (DocString = @"Delete by side effect any occurrences of ELT as a member of SEQ.
  116. SEQ must be a list, a vector, or a string.
  117. The modified SEQ is returned. Comparison is done with `equal'.
  118. If SEQ is not a list, or the first member of SEQ is ELT, deleting it
  119. is not a side effect; it is simply using a different sequence.
  120. Therefore, write `(setq foo (delete element foo))'
  121. to be sure of changing the value of `foo'.")]
  122. public static Shelisp.Object Fdelete (L l, Shelisp.Object elt, Shelisp.Object seq)
  123. {
  124. if (seq is Vector) {
  125. Vector seqv = (Vector)seq;
  126. int i, n;
  127. for (i = n = 0; i < seqv.Length; ++i)
  128. if (!seqv[i].LispEqual (elt))
  129. ++n;
  130. if (n != seqv.Length) {
  131. Shelisp.Object[] p = new Shelisp.Object[n];
  132. for (i = n = 0; i < seqv.Length; ++i)
  133. if (!seqv[i].LispEqual (elt))
  134. p[n++] = seqv[i];
  135. seqv.SetData (p);
  136. }
  137. }
  138. else if (seq is String) {
  139. throw new NotImplementedException ();
  140. }
  141. else {
  142. Shelisp.Object tail, prev;
  143. for (tail = seq, prev = L.Qnil; L.CONSP (tail); tail = L.CDR (tail)) {
  144. // XXX CHECK_LIST_CONS (tail, seq);
  145. if (elt.LispEqual (L.CAR(tail))) {
  146. if (L.NILP (prev))
  147. seq = L.CDR (tail);
  148. else
  149. List.Fsetcdr (l, prev, L.CDR (tail));
  150. }
  151. else
  152. prev = tail;
  153. }
  154. }
  155. return seq;
  156. }
  157. }
  158. }