SchemeCompilation.java 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package kawa.standard;
  2. import gnu.expr.*;
  3. import gnu.kawa.functions.Convert;
  4. import gnu.kawa.functions.Curry1;
  5. import gnu.kawa.functions.CurryExp;
  6. import gnu.mapping.*;
  7. import gnu.text.*;
  8. import kawa.lang.*;
  9. public class SchemeCompilation extends Translator
  10. {
  11. public SchemeCompilation(Language language, SourceMessages messages,
  12. NameLookup lexical, Environment env) {
  13. super(language, messages, lexical, env);
  14. }
  15. public SchemeCompilation(Language language, SourceMessages messages,
  16. NameLookup lexical) {
  17. super(language, messages, lexical);
  18. }
  19. public static final Declaration applyFieldDecl =
  20. Declaration.getDeclarationFromStatic("kawa.standard.Scheme", "applyToArgs");
  21. @Override
  22. public Expression applyFunction(Expression func) {
  23. if (func instanceof LambdaExp)
  24. return null;
  25. else
  26. return new ReferenceExp(applyFieldDecl);
  27. }
  28. @Override
  29. public boolean isApplyFunction (Expression exp)
  30. {
  31. return isSimpleApplyFunction(exp);
  32. }
  33. @Override
  34. public boolean isSimpleApplyFunction (Expression exp)
  35. {
  36. return exp instanceof ReferenceExp
  37. && ((ReferenceExp) exp).getBinding() == applyFieldDecl;
  38. }
  39. /** Should the values of body/block be appended as multiple values?
  40. * Otherwise, just return the result of the final expression.
  41. */
  42. @Override
  43. public boolean appendBodyValues ()
  44. {
  45. return ((Scheme) getLanguage()).appendBodyValues();
  46. }
  47. public static final Lambda lambda = new kawa.lang.Lambda();
  48. public static final Lambda mlambda = lambda;
  49. static {
  50. lambda.setKeywords(Special.optional, Special.rest, Special.key);
  51. }
  52. public static final kawa.repl repl = new kawa.repl(Scheme.instance);
  53. /** If a symbol is lexically unbound, look for a default binding.
  54. * Recognizes {@code typename?} as a type predicate,
  55. * {@code ->typename} as a conversion function,
  56. * plus whatever the overridden method handles.
  57. * @return null if no binding, otherwise an Expression.
  58. */
  59. @Override
  60. public Expression checkDefaultBinding(Symbol symbol, Translator tr) {
  61. Namespace namespace = symbol.getNamespace();
  62. String local = symbol.getLocalPart();
  63. String name = symbol.toString();
  64. int len = name.length();
  65. if (len == 0)
  66. return null;
  67. int llen = local.length();
  68. // Map 'TYPE?' to '(lambda (obj) (instance? obj TYPE))'.
  69. // FIXME - this should be done after/during InlineCalls,
  70. // so we only do this if TYPE is a Type or Class.
  71. if (len > 1 && llen > 1 && name.charAt(len-1) == '?') {
  72. String tlocal = local.substring(0, llen-1).intern();
  73. Symbol tsymbol = namespace.getSymbol(tlocal);
  74. Expression texp = tr.rewrite(tsymbol, false);
  75. if (texp instanceof ReferenceExp) {
  76. Declaration decl = ((ReferenceExp) texp).getBinding();
  77. if (decl == null || decl.getFlag(Declaration.IS_UNKNOWN))
  78. texp = null;
  79. }
  80. else if (! (texp instanceof QuoteExp))
  81. texp = null;
  82. if (texp != null) {
  83. LambdaExp lexp = new LambdaExp(1);
  84. lexp.setSymbol(symbol);
  85. Declaration param = lexp.addDeclaration((Object) null);
  86. param.setFlag(Declaration.IS_PARAMETER);
  87. param.noteValueUnknown();
  88. lexp.body = new ApplyExp(Scheme.instanceOf,
  89. new ReferenceExp(param), texp);
  90. return lexp;
  91. }
  92. }
  93. // Map '->TYPE' to '(lambda (obj) (as TYPE obj))'.
  94. // FIXME - this should be done after/during InlineCalls,
  95. // so we only do this if TYPE is a Type or Class.
  96. if (len > 2 && llen > 2
  97. && name.charAt(0) == '-' && name.charAt(1) == '>') {
  98. String tlocal = local.substring(2).intern();
  99. Symbol tsymbol = namespace.getSymbol(tlocal);
  100. Expression texp = tr.rewrite(tsymbol, false);
  101. if (texp instanceof ReferenceExp) {
  102. Declaration decl = ((ReferenceExp) texp).getBinding();
  103. if (decl == null || decl.getFlag(Declaration.IS_UNKNOWN))
  104. texp = null;
  105. }
  106. else if (! (texp instanceof QuoteExp))
  107. texp = null;
  108. if (texp != null)
  109. return new CurryExp(Curry1.makeConverter, Convert.cast, texp);
  110. }
  111. return super.checkDefaultBinding(symbol, tr);
  112. }
  113. }