PageRenderTime 25ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/java/rainbow/vm/interpreter/QuasiQuotation.java

http://github.com/conanite/rainbow
Java | 408 lines | 341 code | 67 blank | 0 comment | 150 complexity | 2639c6d7e5dfe9f183cc7cce22417faf MD5 | raw file
  1. package rainbow.vm.interpreter;
  2. import rainbow.Nil;
  3. import rainbow.functions.interpreted.InterpretedFunction;
  4. import rainbow.types.ArcObject;
  5. import rainbow.types.Pair;
  6. import rainbow.types.Symbol;
  7. import static rainbow.vm.compiler.QuasiQuoteCompiler.*;
  8. import rainbow.vm.instructions.*;
  9. import rainbow.vm.interpreter.visitor.Visitor;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Map;
  13. public class QuasiQuotation extends ArcObject {
  14. private ArcObject target;
  15. public QuasiQuotation(ArcObject target) {
  16. this.target = target;
  17. }
  18. public ArcObject type() {
  19. return Symbol.mkSym("quasiquotation");
  20. }
  21. public void addInstructions(List i) {
  22. addInstructions(i, target);
  23. }
  24. public String toString() {
  25. return "`" + target;
  26. }
  27. private List<ArcObject> unquotes() {
  28. List l = new ArrayList();
  29. appendUnquotes(l, target, 1);
  30. return l;
  31. }
  32. private void appendUnquotes(List l, ArcObject expr, int nesting) {
  33. if (isUnQuote(expr)) {
  34. if (nesting == 1) {
  35. l.add(expr.cdr().car());
  36. } else {
  37. appendUnquotes(l, expr.cdr().car(), nesting - 1);
  38. }
  39. return;
  40. } else if (isUnQuoteSplicing(expr)) {
  41. if (nesting == 1) {
  42. l.add(expr.cdr().car());
  43. } else {
  44. appendUnquotes(l, expr.cdr().car(), nesting - 1);
  45. }
  46. return;
  47. } else if (isQuasiQuote(expr)) {
  48. appendUnquotes(l, expr.cdr().car(), nesting + 1);
  49. return;
  50. } else if (expr.isNotPair()) {
  51. return;
  52. }
  53. while (!expr.isNotPair()) {
  54. if (isUnQuote(expr) || isQuasiQuote(expr)) { // catch post-dot unquotes
  55. appendUnquotes(l, expr, nesting);
  56. expr = expr.cdr().cdr();
  57. } else {
  58. final ArcObject current = expr.car();
  59. expr = expr.cdr();
  60. if (isUnQuoteSplicing(current)) {
  61. appendUnquotes(l, current, nesting);
  62. } else if (isUnQuote(current) || isQuasiQuote(current) || isPair(current)) {
  63. appendUnquotes(l, current, nesting);
  64. }
  65. }
  66. }
  67. }
  68. public static void addInstructions(List i, ArcObject target) {
  69. addInstructions(i, target, 1);
  70. }
  71. private static void addInstructions(List i, ArcObject expr, int nesting) {
  72. if (isUnQuote(expr)) {
  73. if (nesting == 1) {
  74. expr.cdr().car().addInstructions(i);
  75. } else {
  76. i.add(new Literal(UNQUOTE));
  77. addInstructions(i, expr.cdr().car(), nesting - 1);
  78. i.add(new Listify(2));
  79. }
  80. return;
  81. } else if (isUnQuoteSplicing(expr)) {
  82. if (nesting == 1) {
  83. expr.cdr().car().addInstructions(i);
  84. i.add(new AppendAll());
  85. } else {
  86. i.add(new Literal(UNQUOTE_SPLICING));
  87. addInstructions(i, expr.cdr().car(), nesting - 1);
  88. i.add(new Listify(2));
  89. i.add(new Append());
  90. }
  91. return;
  92. } else if (isQuasiQuote(expr)) {
  93. i.add(new Literal(QUASIQUOTE));
  94. addInstructions(i, expr.cdr().car(), nesting + 1);
  95. i.add(new Listify(2));
  96. return;
  97. } else if (expr.isNotPair()) {
  98. i.add(new Literal(expr));
  99. return;
  100. }
  101. i.add(new NewList());
  102. while (!expr.isNotPair()) {
  103. if (isUnQuote(expr) || isQuasiQuote(expr)) { // catch post-dot unquotes
  104. addInstructions(i, expr, nesting);
  105. expr = expr.cdr().cdr();
  106. i.add(new AppendDot());
  107. } else {
  108. final ArcObject current = expr.car();
  109. expr = expr.cdr();
  110. if (isUnQuoteSplicing(current)) {
  111. addInstructions(i, current, nesting);
  112. } else if (isUnQuote(current) || isQuasiQuote(current) || isPair(current)) {
  113. addInstructions(i, current, nesting);
  114. i.add(new Append());
  115. } else {
  116. i.add(new Literal(current));
  117. i.add(new Append());
  118. }
  119. }
  120. }
  121. if (!(expr instanceof Nil)) {
  122. i.add(new Literal(expr));
  123. i.add(new AppendDot());
  124. }
  125. i.add(new FinishList());
  126. }
  127. public static boolean isQQPair(ArcObject expression, Symbol car) {
  128. return (expression instanceof Pair) && expression.isCar(car) && (expression.cdr().cdr() instanceof Nil);
  129. }
  130. public static boolean isUnQuote(ArcObject expression) {
  131. return isQQPair(expression, UNQUOTE);
  132. }
  133. public static boolean isUnQuoteSplicing(ArcObject expression) {
  134. return isQQPair(expression, UNQUOTE_SPLICING);
  135. }
  136. public static boolean isQuasiQuote(ArcObject expression) {
  137. return isQQPair(expression, QUASIQUOTE);
  138. }
  139. private static boolean isPair(ArcObject expression) {
  140. return expression instanceof Pair;
  141. }
  142. public boolean assigns(int nesting) {
  143. for (ArcObject o : unquotes()) {
  144. if (o.assigns(nesting)) {
  145. return true;
  146. }
  147. }
  148. return false;
  149. }
  150. public boolean hasClosures() {
  151. for (ArcObject o : unquotes()) {
  152. if (o instanceof InterpretedFunction) {
  153. if (((InterpretedFunction)o).requiresClosure()) {
  154. return true;
  155. }
  156. } else if (o.hasClosures()) {
  157. return true;
  158. }
  159. }
  160. return false;
  161. }
  162. public ArcObject inline(BoundSymbol p, ArcObject arg, boolean unnest, int lexicalNesting, int paramIndex) {
  163. return new QuasiQuotation(inline(p, arg, unnest, lexicalNesting, paramIndex, target, 1));
  164. }
  165. private static ArcObject inline(BoundSymbol p, ArcObject arg, boolean unnest, int lexicalNesting, int paramIndex, ArcObject expr, int nesting) {
  166. if (isUnQuote(expr)) {
  167. if (nesting == 1) {
  168. return Pair.buildFrom(UNQUOTE, expr.cdr().car().inline(p, arg, unnest, lexicalNesting, paramIndex));
  169. } else {
  170. return Pair.buildFrom(UNQUOTE, inline(p, arg, unnest, lexicalNesting, paramIndex, expr.cdr().car(), nesting - 1));
  171. }
  172. } else if (isUnQuoteSplicing(expr)) {
  173. if (nesting == 1) {
  174. return Pair.buildFrom(UNQUOTE_SPLICING, expr.cdr().car().inline(p, arg, unnest, lexicalNesting, paramIndex));
  175. } else {
  176. return Pair.buildFrom(UNQUOTE_SPLICING, inline(p, arg, unnest, lexicalNesting, paramIndex, expr.cdr().car(), nesting - 1));
  177. }
  178. } else if (isQuasiQuote(expr)) {
  179. return Pair.buildFrom(QUASIQUOTE, inline(p, arg, unnest, lexicalNesting, paramIndex, expr.cdr().car(), nesting + 1));
  180. } else if (expr.isNotPair()) {
  181. return expr;
  182. }
  183. List list = new ArrayList();
  184. ArcObject last = NIL;
  185. while (!expr.isNotPair()) {
  186. if (isUnQuote(expr) || isQuasiQuote(expr)) { // catch post-dot unquotes
  187. last = inline(p, arg, unnest, lexicalNesting, paramIndex, expr, nesting);
  188. expr = expr.cdr().cdr();
  189. } else {
  190. final ArcObject current = expr.car();
  191. expr = expr.cdr();
  192. if (isUnQuoteSplicing(current)) {
  193. list.add(inline(p, arg, unnest, lexicalNesting, paramIndex, current, nesting));
  194. } else if (isUnQuote(current) || isQuasiQuote(current) || isPair(current)) {
  195. list.add(inline(p, arg, unnest, lexicalNesting, paramIndex, current, nesting));
  196. } else {
  197. list.add(current);
  198. }
  199. }
  200. }
  201. if (!(expr instanceof Nil)) {
  202. last = expr;
  203. }
  204. return Pair.buildFrom(list, last);
  205. }
  206. public ArcObject inline(StackSymbol p, ArcObject arg, int paramIndex) {
  207. return new QuasiQuotation(inline(p, arg, paramIndex, target, 1));
  208. }
  209. private static ArcObject inline(StackSymbol p, ArcObject arg, int paramIndex, ArcObject expr, int nesting) {
  210. if (isUnQuote(expr)) {
  211. if (nesting == 1) {
  212. return Pair.buildFrom(UNQUOTE, expr.cdr().car().inline(p, arg, paramIndex));
  213. } else {
  214. return Pair.buildFrom(UNQUOTE, inline(p, arg, paramIndex, expr.cdr().car(), nesting - 1));
  215. }
  216. } else if (isUnQuoteSplicing(expr)) {
  217. if (nesting == 1) {
  218. return Pair.buildFrom(UNQUOTE_SPLICING, expr.cdr().car().inline(p, arg, paramIndex));
  219. } else {
  220. return Pair.buildFrom(UNQUOTE_SPLICING, inline(p, arg, paramIndex, expr.cdr().car(), nesting - 1));
  221. }
  222. } else if (isQuasiQuote(expr)) {
  223. return Pair.buildFrom(QUASIQUOTE, inline(p, arg, paramIndex, expr.cdr().car(), nesting + 1));
  224. } else if (expr.isNotPair()) {
  225. return expr;
  226. }
  227. List list = new ArrayList();
  228. ArcObject last = NIL;
  229. while (!expr.isNotPair()) {
  230. if (isUnQuote(expr) || isQuasiQuote(expr)) { // catch post-dot unquotes
  231. last = inline(p, arg, paramIndex, expr, nesting);
  232. expr = expr.cdr().cdr();
  233. } else {
  234. final ArcObject current = expr.car();
  235. expr = expr.cdr();
  236. if (isUnQuoteSplicing(current)) {
  237. list.add(inline(p, arg, paramIndex, current, nesting));
  238. } else if (isUnQuote(current) || isQuasiQuote(current) || isPair(current)) {
  239. list.add(inline(p, arg, paramIndex, current, nesting));
  240. } else {
  241. list.add(current);
  242. }
  243. }
  244. }
  245. if (!(expr instanceof Nil)) {
  246. last = expr;
  247. }
  248. return Pair.buildFrom(list, last);
  249. }
  250. public ArcObject nest(int threshold) {
  251. return new QuasiQuotation(nest(threshold, target, 1));
  252. }
  253. private static ArcObject nest(int threshold, ArcObject expr, int nesting) {
  254. if (isUnQuote(expr)) {
  255. if (nesting == 1) {
  256. return Pair.buildFrom(UNQUOTE, expr.cdr().car().nest(threshold));
  257. } else {
  258. return Pair.buildFrom(UNQUOTE, nest(threshold, expr.cdr().car(), nesting - 1));
  259. }
  260. } else if (isUnQuoteSplicing(expr)) {
  261. if (nesting == 1) {
  262. return Pair.buildFrom(UNQUOTE_SPLICING, expr.cdr().car().nest(threshold));
  263. } else {
  264. return Pair.buildFrom(UNQUOTE_SPLICING, nest(threshold, expr.cdr().car(), nesting - 1));
  265. }
  266. } else if (isQuasiQuote(expr)) {
  267. return Pair.buildFrom(QUASIQUOTE, nest(threshold, expr.cdr().car(), nesting + 1));
  268. } else if (expr.isNotPair()) {
  269. return expr;
  270. }
  271. List list = new ArrayList();
  272. ArcObject last = NIL;
  273. while (!expr.isNotPair()) {
  274. if (isUnQuote(expr) || isQuasiQuote(expr)) { // catch post-dot unquotes
  275. last = nest(threshold, expr, nesting);
  276. expr = expr.cdr().cdr();
  277. } else {
  278. final ArcObject current = expr.car();
  279. expr = expr.cdr();
  280. if (isUnQuoteSplicing(current) || isUnQuote(current) || isQuasiQuote(current) || isPair(current)) {
  281. list.add(nest(threshold, current, nesting));
  282. } else {
  283. list.add(current);
  284. }
  285. }
  286. }
  287. if (!(expr instanceof Nil)) {
  288. last = expr;
  289. }
  290. return Pair.buildFrom(list, last);
  291. }
  292. public ArcObject replaceBoundSymbols(Map<Symbol, Integer> lexicalBindings) {
  293. return new QuasiQuotation(replaceBoundSymbols(lexicalBindings, target, 1));
  294. }
  295. private static ArcObject replaceBoundSymbols(Map<Symbol, Integer> lexicalBindings, ArcObject expr, int nesting) {
  296. if (isUnQuote(expr)) {
  297. if (nesting == 1) {
  298. return Pair.buildFrom(UNQUOTE, expr.cdr().car().replaceBoundSymbols(lexicalBindings));
  299. } else {
  300. return Pair.buildFrom(UNQUOTE, replaceBoundSymbols(lexicalBindings, expr.cdr().car(), nesting - 1));
  301. }
  302. } else if (isUnQuoteSplicing(expr)) {
  303. if (nesting == 1) {
  304. return Pair.buildFrom(UNQUOTE_SPLICING, expr.cdr().car().replaceBoundSymbols(lexicalBindings));
  305. } else {
  306. return Pair.buildFrom(UNQUOTE_SPLICING, replaceBoundSymbols(lexicalBindings, expr.cdr().car(), nesting - 1));
  307. }
  308. } else if (isQuasiQuote(expr)) {
  309. return Pair.buildFrom(QUASIQUOTE, replaceBoundSymbols(lexicalBindings, expr.cdr().car(), nesting + 1));
  310. } else if (expr.isNotPair()) {
  311. return expr;
  312. }
  313. List list = new ArrayList();
  314. ArcObject last = NIL;
  315. while (!expr.isNotPair()) {
  316. if (isUnQuote(expr) || isQuasiQuote(expr)) { // catch post-dot unquotes
  317. last = replaceBoundSymbols(lexicalBindings, expr, nesting);
  318. expr = expr.cdr().cdr();
  319. } else {
  320. final ArcObject current = expr.car();
  321. expr = expr.cdr();
  322. if (isUnQuoteSplicing(current) || isUnQuote(current) || isQuasiQuote(current) || isPair(current)) {
  323. list.add(replaceBoundSymbols(lexicalBindings, current, nesting));
  324. } else {
  325. list.add(current);
  326. }
  327. }
  328. }
  329. if (!(expr instanceof Nil)) {
  330. last = expr;
  331. }
  332. return Pair.buildFrom(list, last);
  333. }
  334. public void visit(Visitor v) {
  335. v.accept(this);
  336. for (ArcObject o : unquotes()) {
  337. o.visit(v);
  338. }
  339. v.end(this);
  340. }
  341. }