Q2Translator.java 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. package gnu.q2.lang;
  2. import gnu.bytecode.Type;
  3. import gnu.kawa.functions.MakeSplice;
  4. import gnu.kawa.lispexpr.LispLanguage;
  5. import gnu.mapping.Procedure;
  6. import gnu.expr.*;
  7. import gnu.text.*;
  8. import gnu.lists.*;
  9. import gnu.mapping.Symbol;
  10. import kawa.lang.*;
  11. import kawa.standard.Scheme;
  12. import kawa.standard.SchemeCompilation;
  13. import java.util.ArrayList;
  14. import java.util.Stack;
  15. public class Q2Translator extends SchemeCompilation
  16. {
  17. public Q2Translator (Language language, SourceMessages messages, NameLookup lexical)
  18. {
  19. super(language, messages, lexical);
  20. }
  21. Operator checkIfOperator(Object obj) {
  22. if (obj instanceof Symbol && ! Q2.instance.selfEvaluatingSymbol(obj)) {
  23. Expression func = rewrite(obj, true);
  24. Declaration decl;
  25. Object value;
  26. if (func instanceof ReferenceExp
  27. && (decl = ((ReferenceExp) func).getBinding()) != null
  28. && (value = decl.getConstantValue()) instanceof Operator)
  29. return (Operator) value;
  30. } else if (obj instanceof Operator)
  31. return (Operator) obj;
  32. return null;
  33. }
  34. /** Split list according to operator-precedence priorities.
  35. */
  36. public static Object partition (Object p, Q2Translator tr)
  37. {
  38. // A stack of: Fence, (arg-list, arg-last, Pair, Operator)*
  39. // The "value" of each Pair<Operator> is the same as the following Operator.
  40. // The invariant is that for each i, where i is 0, 4, 11, ..., we have:
  41. // ((Operator)st.get(i)).rprio < ((Operator)st.get(i+4)).lprio
  42. Stack st = new Stack();
  43. st.add(Operator.FENCE);
  44. Object larg = p;
  45. Pair prev = null;
  46. for (;;)
  47. {
  48. if (p instanceof SyntaxForm)
  49. ; // FIXME
  50. Operator op = null;
  51. Pair pp;
  52. if (! (p instanceof Pair))
  53. {
  54. op = Operator.FENCE;
  55. pp = null;
  56. }
  57. else
  58. {
  59. pp = (Pair) p;
  60. Object obj = pp.getCar();
  61. op = tr.checkIfOperator(obj);
  62. }
  63. if (op != null)
  64. {
  65. if (prev == null)
  66. larg = LList.Empty;
  67. else if (p instanceof Pair)
  68. prev.setCdrBackdoor(LList.Empty);
  69. int stsz = st.size();
  70. Operator topop = (Operator) st.get(stsz-1);
  71. while (op.lprio <= topop.rprio)
  72. {
  73. PairWithPosition oppair = (PairWithPosition) st.get(stsz-2);
  74. if ((topop.flags & Operator.RHS_NEEDED) != 0
  75. && larg == LList.Empty)
  76. tr.error('e', "missing right operand after "+topop.getName(), oppair);
  77. LList prefixArgs = (LList) st.get(stsz-4);
  78. if (topop.lprio == Operator.UNARY_PRIO) {
  79. Pair prefixTail = (Pair) st.get(stsz-3);
  80. Object narg = topop.combine(LList.Empty, larg,
  81. oppair);
  82. narg = new Pair(narg, LList.Empty);
  83. if (prefixTail == null)
  84. larg = narg;
  85. else {
  86. larg = prefixArgs;
  87. prefixTail.setCdrBackdoor(narg);
  88. }
  89. } else
  90. larg = topop.combine(prefixArgs, larg, oppair);
  91. stsz -= 4;
  92. st.setSize(stsz);
  93. topop = (Operator) st.get(stsz-1);
  94. }
  95. if (pp == null)
  96. break;
  97. st.add(larg);
  98. st.add(prev);
  99. st.add(pp);
  100. st.add(op);
  101. larg = pp.getCdr();
  102. prev = null;
  103. }
  104. else
  105. prev = pp;
  106. p = pp.getCdr();
  107. }
  108. return larg;
  109. }
  110. public Expression makeBody(Expression[] exps) {
  111. int nlen = exps.length;
  112. for (int i = 0; i < nlen-1; i++) {
  113. Expression exp = exps[i];
  114. if (exp instanceof IfExp) {
  115. IfExp iexp = (IfExp) exp;
  116. if (iexp.getElseClause() == null) {
  117. Expression[] rest = new Expression[nlen-i-1];
  118. System.arraycopy(exps, i+1, rest, 0, rest.length);
  119. iexp = new IfExp(iexp.getTest(), iexp.getThenClause(),
  120. makeBody(rest));
  121. iexp.setLine(exp);
  122. if (i == 0)
  123. return iexp;
  124. Expression[] init = new Expression[i+1];
  125. System.arraycopy(exps, 0, init, 0, i);
  126. init[i] = iexp;
  127. return super.makeBody(init);
  128. }
  129. }
  130. }
  131. return super.makeBody(exps);
  132. }
  133. public void scanForm (Object st, ScopeExp defs)
  134. {
  135. if (st instanceof LList)
  136. st = partition(st, this);
  137. if (st != LList.Empty)
  138. super.scanForm(st, defs);
  139. }
  140. public Expression rewrite (Object exp, boolean function)
  141. {
  142. if (exp == LList.Empty)
  143. return QuoteExp.voidExp;
  144. return super.rewrite(exp, function);
  145. }
  146. public Expression rewrite_pair (Pair p, boolean function)
  147. {
  148. Object partitioned = partition(p, this);
  149. if (partitioned instanceof Pair) {
  150. Pair pair = (Pair) partitioned;
  151. Object p_car = pair.getCar();
  152. if (p_car instanceof Pair
  153. && ((Pair) p_car).getCar() == LispLanguage.splice_sym)
  154. return new ApplyExp(MakeSplice.quoteInstance,
  155. rewrite_car((Pair)((Pair) p_car).getCdr(), function));
  156. else {
  157. Expression exp = super.rewrite_pair(pair, function);
  158. ApplyExp app;
  159. if (exp instanceof ApplyExp) {
  160. Expression fun = (app = (ApplyExp) exp).getFunction();
  161. if (isApplyFunction(fun))
  162. exp = convertApply(app);
  163. else if (fun instanceof LambdaExp && app.getArgCount() == 0)
  164. return fun;
  165. }
  166. return exp;
  167. }
  168. }
  169. else
  170. return rewrite(partitioned, function);
  171. }
  172. /** If the argument has zero arguments, should we still apply it? */
  173. public static boolean applyNullary(Expression exp) {
  174. if (exp instanceof ReferenceExp) {
  175. Declaration decl =
  176. Declaration.followAliases(((ReferenceExp) exp).getBinding());
  177. if (decl != null) {
  178. if (decl.isProcedureDecl())
  179. return true;
  180. if (decl.getFlag(Declaration.STATIC_SPECIFIED)
  181. && decl.getFlag(Declaration.IS_CONSTANT)) { // kludge
  182. Type type = decl.getType();
  183. if ("gnu.kawa.lispexpr.LangObjType" == type.getName())
  184. return true;
  185. }
  186. }
  187. }
  188. if (exp instanceof QuoteExp) {
  189. Object val = exp.valueIfConstant();
  190. return val instanceof Type || val instanceof Class;
  191. }
  192. return false;
  193. }
  194. public static Expression convertApply(ApplyExp exp) {
  195. Expression[] args = exp.getArgs();
  196. int nargs = args.length;
  197. Expression arg0 = args[0];
  198. if (nargs == 1 && ! applyNullary(arg0)) {
  199. if (arg0 instanceof IfExp
  200. && ((IfExp) arg0).getElseClause() == null)
  201. arg0 = new BeginExp(args);
  202. return arg0;
  203. }
  204. ArrayList<Expression> rargs = new ArrayList<Expression>();
  205. LetExp let = null;
  206. for (int i = 0; i < nargs; i++) {
  207. Expression arg = exp.getArg(i);
  208. Expression barg;
  209. if (arg instanceof LetExp && arg.getFlag(LetExp.IS_BODY_SCOPE)
  210. // Can we get more than one LetExp? FIXME
  211. && let == null) {
  212. barg = ((LetExp) arg).getBody();
  213. } else
  214. barg = arg;
  215. if (barg instanceof ApplyExp) {
  216. ApplyExp aarg = (ApplyExp) barg;
  217. if (aarg.isAppendValues()) {
  218. if (arg != barg)
  219. let = (LetExp) arg;
  220. int naarg = aarg.getArgCount();
  221. for (int j = 0; j < naarg; j++) {
  222. Expression xaarg = aarg.getArg(j);
  223. if (xaarg instanceof SetExp) {
  224. xaarg = new ApplyExp(MakeSplice.quoteInstance,
  225. new BeginExp(xaarg, QuoteExp.emptyExp));
  226. if (exp.firstSpliceArg == -1
  227. || exp.firstSpliceArg > j)
  228. exp.firstSpliceArg = j;
  229. }
  230. rargs.add(xaarg);
  231. }
  232. continue;
  233. }
  234. }
  235. rargs.add(arg);
  236. }
  237. args = rargs.toArray(new Expression[rargs.size()]);
  238. Procedure proc = Scheme.applyToArgs;
  239. exp.setFuncArgs(new QuoteExp(proc), args);
  240. if (let != null) {
  241. let.setBody(exp);
  242. return let;
  243. }
  244. return exp;
  245. }
  246. }