BracketApply.java 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package gnu.kawa.lispexpr;
  2. import gnu.bytecode.*;
  3. import gnu.expr.*;
  4. import gnu.lists.*;
  5. import kawa.lang.*;
  6. import gnu.kawa.reflect.LazyType;
  7. /** Expand {@code $bracket-apply$} macro.
  8. * This is produced by the reader syntax {@code exp[args]}.
  9. * Currently, it us only use for array types: {@code type[]}.
  10. * In the future it might have other uses - perhaps parameterized tyoes,
  11. * as in Scala.
  12. */
  13. public class BracketApply extends Syntax
  14. {
  15. public static final BracketApply instance = new BracketApply();
  16. public Expression rewrite (Object obj, Translator tr)
  17. {
  18. if (! (obj instanceof Pair))
  19. return tr.syntaxError ("internal error - $bracket-apply$ missing functor");
  20. Pair pair = (Pair) obj;
  21. int length = LList.listLength(pair, false)-1;
  22. Expression arg0 = tr.rewrite_car(pair, false);
  23. Object val = arg0.valueIfConstant();
  24. Object pairCdr = pair.getCdr();
  25. // Special-case promise[T] to yield a LazyType:
  26. if (length == 1 && val == LangObjType.promiseType && pairCdr instanceof Pair)
  27. {
  28. Expression arg1 = tr.rewrite_car((Pair) pairCdr, false);
  29. Object val1 = arg1.valueIfConstant();
  30. if (val1 instanceof Type)
  31. return new QuoteExp(LazyType.getInstance(LazyType.lazyType, (Type) val1));
  32. }
  33. Class clas;
  34. if (val instanceof Class)
  35. clas = (Class) val;
  36. else if (val instanceof ObjectType) {
  37. Type rtype = ((ObjectType) val).getRawType();
  38. clas = rtype.getReflectClass();
  39. } else
  40. clas = null;
  41. if (length > 0 && clas != null) {
  42. java.lang.reflect.TypeVariable[] vars = clas.getTypeParameters();
  43. if (vars.length != length)
  44. return tr.syntaxError("expected "+vars.length+" parameters for type "+val);
  45. Type[] params = new Type[length];
  46. for (int i = 0; i < length; i++) {
  47. Pair pp = (Pair) pairCdr;
  48. Expression arg1 = tr.rewrite_car(pp, false);
  49. Type type1 = tr.getLanguage().getTypeFor(arg1, false);
  50. TypeVariable tvar = TypeVariable.make(vars[i]);
  51. if (type1 == null) {
  52. tr.errorWithPosition("unrecognized parameter type "+pp.getCar(),
  53. pp);
  54. type1 = Type.objectType;
  55. }
  56. else {
  57. int comp = tvar.compare(type1);
  58. Language language = tr.getLanguage();
  59. if (comp < 0)
  60. tr.error('e', "type parameter "+tvar.getName()+" must extend "+language.formatType(tvar.getRawType())+" which is incompatible with "+language.formatType(type1));
  61. }
  62. params[i] = type1;
  63. pairCdr = pp.getCdr();
  64. }
  65. if (val instanceof GenArrayType && length == 1) {
  66. int rank = ((GenArrayType) val).rank();
  67. return new QuoteExp(new GenArrayType(rank, params[0]));
  68. }
  69. return new QuoteExp(new ParameterizedType((ClassType) ClassType.make(clas), params));
  70. }
  71. if (pair.getCdr() != LList.Empty)
  72. return tr.syntaxError ("unrecognized syntax: type[args]");
  73. if (val instanceof Type)
  74. return new QuoteExp(ArrayType.make((Type) val));
  75. if (val instanceof Class)
  76. {
  77. Class cls = (Class) val;
  78. return new QuoteExp(new ArrayType(ClassType.make(cls)).getReflectClass());
  79. }
  80. Type typ = tr.getLanguage().getTypeFor(arg0, false);
  81. if (typ != null)
  82. return new QuoteExp(ArrayType.make(typ));
  83. return tr.syntaxError ("[] syntax not implemented for non-constant: "+arg0+"::"+arg0.getClass().getName());
  84. }
  85. }