123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- package gnu.kawa.lispexpr;
- import gnu.bytecode.*;
- import gnu.expr.*;
- import gnu.lists.*;
- import kawa.lang.*;
- import gnu.kawa.reflect.LazyType;
- /** Expand {@code $bracket-apply$} macro.
- * This is produced by the reader syntax {@code exp[args]}.
- * Currently, it us only use for array types: {@code type[]}.
- * In the future it might have other uses - perhaps parameterized tyoes,
- * as in Scala.
- */
- public class BracketApply extends Syntax
- {
- public static final BracketApply instance = new BracketApply();
- public Expression rewrite (Object obj, Translator tr)
- {
- if (! (obj instanceof Pair))
- return tr.syntaxError ("internal error - $bracket-apply$ missing functor");
- Pair pair = (Pair) obj;
- int length = LList.listLength(pair, false)-1;
- Expression arg0 = tr.rewrite_car(pair, false);
- Object val = arg0.valueIfConstant();
- Object pairCdr = pair.getCdr();
- // Special-case promise[T] to yield a LazyType:
- if (length == 1 && val == LangObjType.promiseType && pairCdr instanceof Pair)
- {
- Expression arg1 = tr.rewrite_car((Pair) pairCdr, false);
- Object val1 = arg1.valueIfConstant();
- if (val1 instanceof Type)
- return new QuoteExp(LazyType.getInstance(LazyType.lazyType, (Type) val1));
- }
- Class clas;
- if (val instanceof Class)
- clas = (Class) val;
- else if (val instanceof ObjectType) {
- Type rtype = ((ObjectType) val).getRawType();
- clas = rtype.getReflectClass();
- } else
- clas = null;
- if (length > 0 && clas != null) {
- java.lang.reflect.TypeVariable[] vars = clas.getTypeParameters();
- if (vars.length != length)
- return tr.syntaxError("expected "+vars.length+" parameters for type "+val);
- Type[] params = new Type[length];
- for (int i = 0; i < length; i++) {
- Pair pp = (Pair) pairCdr;
- Expression arg1 = tr.rewrite_car(pp, false);
- Type type1 = tr.getLanguage().getTypeFor(arg1, false);
- TypeVariable tvar = TypeVariable.make(vars[i]);
- if (type1 == null) {
- tr.errorWithPosition("unrecognized parameter type "+pp.getCar(),
- pp);
- type1 = Type.objectType;
- }
- else {
- int comp = tvar.compare(type1);
- Language language = tr.getLanguage();
- if (comp < 0)
- tr.error('e', "type parameter "+tvar.getName()+" must extend "+language.formatType(tvar.getRawType())+" which is incompatible with "+language.formatType(type1));
- }
- params[i] = type1;
- pairCdr = pp.getCdr();
- }
- if (val instanceof GenArrayType && length == 1) {
- int rank = ((GenArrayType) val).rank();
- return new QuoteExp(new GenArrayType(rank, params[0]));
- }
- return new QuoteExp(new ParameterizedType((ClassType) ClassType.make(clas), params));
- }
- if (pair.getCdr() != LList.Empty)
- return tr.syntaxError ("unrecognized syntax: type[args]");
- if (val instanceof Type)
- return new QuoteExp(ArrayType.make((Type) val));
- if (val instanceof Class)
- {
- Class cls = (Class) val;
- return new QuoteExp(new ArrayType(ClassType.make(cls)).getReflectClass());
- }
- Type typ = tr.getLanguage().getTypeFor(arg0, false);
- if (typ != null)
- return new QuoteExp(ArrayType.make(typ));
- return tr.syntaxError ("[] syntax not implemented for non-constant: "+arg0+"::"+arg0.getClass().getName());
- }
- }
|