use of org.eclipse.ceylon.model.typechecker.model.Generic in project ceylon by eclipse.
the class InvocationGenerator method getTypeArguments.
private Map<TypeParameter, Type> getTypeArguments(Tree.Primary p) {
if (p instanceof Tree.StaticMemberOrTypeExpression) {
Tree.StaticMemberOrTypeExpression smote = (Tree.StaticMemberOrTypeExpression) p;
final Declaration d = smote.getDeclaration();
final boolean hasTargs = d != null && d.getContainer() instanceof Generic && ((Generic) d.getContainer()).isParameterized();
final boolean hasParentTargs = TypeUtils.isStaticWithGenericContainer(d);
if (hasTargs && ModelUtil.isConstructor(d)) {
return smote.getTarget().getTypeArguments();
} else if (hasParentTargs) {
if (smote.getTypeArguments() != null && !smote.getTypeArguments().getTypeModels().isEmpty()) {
// If the type is static AND has type arguments of its own, we need to merge them
Map<TypeParameter, Type> targs = new HashMap<>();
targs.putAll(smote.getTarget().getTypeArguments());
targs.putAll(smote.getTarget().getQualifyingType().getTypeArguments());
return targs;
}
return smote.getTarget().getQualifyingType().getTypeArguments();
} else if (d instanceof Functional) {
Map<TypeParameter, Type> targs = TypeUtils.matchTypeParametersWithArguments(d.getTypeParameters(), smote.getTypeArguments() == null ? null : smote.getTypeArguments().getTypeModels());
if (targs == null) {
gen.out("/*TARGS != TPARAMS!!!!*/");
}
return targs;
}
} else if (p instanceof Tree.ExtendedTypeExpression) {
Tree.ExtendedTypeExpression ete = (Tree.ExtendedTypeExpression) p;
return ete.getTarget().getTypeArguments();
}
return null;
}
use of org.eclipse.ceylon.model.typechecker.model.Generic in project ceylon by eclipse.
the class BmeGenerator method createTypeArguments.
/**
* Create a map with type arguments from the type parameter list in the expression's declaration and the
* type argument list in the expression itself.
*/
static Map<TypeParameter, Type> createTypeArguments(final Tree.StaticMemberOrTypeExpression expr) {
List<TypeParameter> tparams = null;
Declaration declaration = expr.getDeclaration();
if (declaration instanceof Generic) {
tparams = declaration.getTypeParameters();
} else if (declaration instanceof TypedDeclaration && ((TypedDeclaration) declaration).getType() != null && ((TypedDeclaration) declaration).getType().isTypeConstructor()) {
tparams = ((TypedDeclaration) declaration).getType().getDeclaration().getTypeParameters();
} else {
expr.addUnexpectedError("Getting type parameters from unidentified declaration type " + declaration, Backend.JavaScript);
return null;
}
final HashMap<TypeParameter, Type> targs = new HashMap<>();
TypeArguments typeArguments = expr.getTypeArguments();
if (typeArguments != null) {
List<Type> typeModels = typeArguments.getTypeModels();
if (typeModels != null) {
final Iterator<Type> iter = typeModels.iterator();
for (TypeParameter tp : tparams) {
Type pt = iter.hasNext() ? iter.next() : tp.getDefaultTypeArgument();
targs.put(tp, pt);
}
}
}
return targs;
}
use of org.eclipse.ceylon.model.typechecker.model.Generic in project ceylon by eclipse.
the class DeclarationVisitor method visit.
@Override
public void visit(Tree.TypeConstraint that) {
String name = name(that.getIdentifier());
TypeParameter p = (TypeParameter) scope.getDirectMember(name, null, false);
if (p == null && scope instanceof Generic) {
// TODO: just look at the most recent
p = searchForTypeParameter(name, (Generic) scope);
}
that.setDeclarationModel(p);
if (p == null) {
that.addError("no matching type parameter for constraint: '" + name + "'", 2500);
p = new TypeParameter();
p.setDeclaration(declaration);
that.setDeclarationModel(p);
visitDeclaration(that, p);
} else {
if (that.getTypeParameterList() != null) {
p.setTypeConstructor(true);
}
if (p.isConstrained()) {
that.addError("duplicate constraint list for type parameter: '" + name + "'");
}
p.setConstrained(true);
}
Scope o = enterScope(p);
super.visit(that);
exitScope(o);
if (that.getAbstractedType() != null) {
that.addUnsupportedError("lower bound type constraints are not yet supported");
}
}
use of org.eclipse.ceylon.model.typechecker.model.Generic in project ceylon by eclipse.
the class TypeUtils method encodeForRuntime.
public static void encodeForRuntime(final Node that, final Declaration d, final GenerateJsVisitor gen, final RuntimeMetamodelAnnotationGenerator annGen) {
gen.out("function(){return{mod:$CCMM$");
List<TypeParameter> tparms = d instanceof Generic ? d.getTypeParameters() : null;
List<Type> satisfies = null;
List<Type> caseTypes = null;
if (d instanceof Class) {
Class _cd = (Class) d;
if (_cd.getExtendedType() != null) {
gen.out(",'super':");
metamodelTypeNameOrList(false, that, d.getUnit().getPackage(), _cd.getExtendedType(), null, gen);
}
// Parameter types
if (_cd.getParameterList() != null) {
gen.out(",", MetamodelGenerator.KEY_PARAMS, ":");
encodeParameterListForRuntime(false, that, _cd.getParameterList(), gen);
}
satisfies = _cd.getSatisfiedTypes();
caseTypes = _cd.getCaseTypes();
} else if (d instanceof Interface) {
Interface _id = (Interface) d;
satisfies = _id.getSatisfiedTypes();
caseTypes = _id.getCaseTypes();
if (_id.isAlias()) {
ArrayList<Type> s2 = new ArrayList<>(satisfies.size() + 1);
s2.add(_id.getExtendedType());
s2.addAll(satisfies);
satisfies = s2;
}
} else if (d instanceof FunctionOrValue) {
gen.out(",", MetamodelGenerator.KEY_TYPE, ":");
if (d instanceof Function && ((Function) d).getParameterLists().size() > 1) {
Type callableType = ((Function) d).getTypedReference().getFullType();
// This needs a new setting to resolve types but not type parameters
metamodelTypeNameOrList(false, that, d.getUnit().getPackage(), that.getUnit().getCallableReturnType(callableType), null, gen);
} else {
// This needs a new setting to resolve types but not type parameters
metamodelTypeNameOrList(false, that, d.getUnit().getPackage(), ((FunctionOrValue) d).getType(), null, gen);
}
if (d instanceof Function) {
gen.out(",", MetamodelGenerator.KEY_PARAMS, ":");
// Parameter types of the first parameter list
encodeParameterListForRuntime(false, that, ((Function) d).getFirstParameterList(), gen);
tparms = d.getTypeParameters();
}
} else if (d instanceof Constructor) {
gen.out(",", MetamodelGenerator.KEY_PARAMS, ":");
encodeParameterListForRuntime(false, that, ((Constructor) d).getFirstParameterList(), gen);
}
if (!d.isToplevel()) {
// Find the first container that is a Declaration
Declaration _cont = ModelUtil.getContainingDeclaration(d);
// Skip over anonymous types/funs as well as local non-captured fields
while (_cont.isAnonymous() || !(_cont.isToplevel() || _cont.isClassOrInterfaceMember() || _cont instanceof Value == false)) {
// Neither do we skip classes, even if they're anonymous
if ((_cont instanceof Value && (((Value) _cont).isJsCaptured())) || _cont instanceof Class) {
break;
}
Declaration __d = ModelUtil.getContainingDeclaration(_cont);
if (__d == null)
break;
_cont = __d;
}
gen.out(",$cont:");
boolean generateName = true;
if ((_cont.getName() != null && _cont.isAnonymous() && _cont instanceof Function) || (_cont instanceof Value && !((Value) _cont).isTransient())) {
// Anon functions don't have metamodel so go up until we find a non-anon container
Declaration _supercont = ModelUtil.getContainingDeclaration(_cont);
while (_supercont != null && _supercont.getName() != null && _supercont.isAnonymous()) {
_supercont = ModelUtil.getContainingDeclaration(_supercont);
}
if (_supercont == null) {
// If the container is a package, add it because this isn't really toplevel
generateName = false;
gen.out("0");
} else {
_cont = _supercont;
}
}
if (generateName) {
if (_cont instanceof Value) {
if (AttributeGenerator.defineAsProperty(_cont)) {
gen.qualify(that, _cont);
}
gen.out(gen.getNames().getter(_cont, true));
} else if (_cont instanceof Setter) {
gen.out("{setter:");
if (AttributeGenerator.defineAsProperty(_cont)) {
gen.qualify(that, _cont);
gen.out(gen.getNames().getter(((Setter) _cont).getGetter(), true), ".set");
} else {
gen.out(gen.getNames().setter(((Setter) _cont).getGetter()));
}
gen.out("}");
} else {
boolean inProto = gen.opts.isOptimize() && (_cont.getContainer() instanceof TypeDeclaration);
final String path = gen.qualifiedPath(that, _cont, inProto);
if (path != null && !path.isEmpty()) {
gen.out(path, ".");
}
final String contName = gen.getNames().name(_cont);
gen.out(contName);
}
}
}
if (tparms != null && !tparms.isEmpty()) {
gen.out(",", MetamodelGenerator.KEY_TYPE_PARAMS, ":{");
encodeTypeParametersForRuntime(that, d, tparms, true, gen);
gen.out("}");
}
if (satisfies != null && !satisfies.isEmpty()) {
gen.out(",", MetamodelGenerator.KEY_SATISFIES, ":[");
boolean first = true;
for (Type st : satisfies) {
if (!first)
gen.out(",");
first = false;
metamodelTypeNameOrList(false, that, d.getUnit().getPackage(), st, null, gen);
}
gen.out("]");
}
if (caseTypes != null && !caseTypes.isEmpty()) {
gen.out(",of:[");
boolean first = true;
for (Type st : caseTypes) {
// teeheehee
final TypeDeclaration std = st.getDeclaration();
if (!first)
gen.out(",");
first = false;
if (ModelUtil.isConstructor(std)) {
if (std.isAnonymous()) {
// Value constructor
gen.out(gen.getNames().name(d), ".", gen.getNames().valueConstructorName(std));
} else {
gen.out("/*TODO callable constructor*/");
}
} else if (std.isAnonymous()) {
if (std.isStatic()) {
gen.out(gen.getNames().name(ModelUtil.getContainingDeclaration(std)), ".$st$.", gen.getNames().objectName(std));
} else {
gen.out(gen.getNames().getter(std, true));
}
} else {
metamodelTypeNameOrList(false, that, d.getUnit().getPackage(), st, null, gen);
}
}
gen.out("]");
}
if (annGen != null) {
annGen.generateAnnotations();
}
// Path to its model
gen.out(",d:");
outputModelPath(d, gen);
gen.out("};}");
}
use of org.eclipse.ceylon.model.typechecker.model.Generic in project ceylon by eclipse.
the class JsonPackage method getTypeFromJson.
/**
* Looks up a type from model data, creating it if necessary. The returned type will have its
* type parameters substituted if needed.
*/
private Type getTypeFromJson(Map<String, Object> m, Declaration container, List<TypeParameter> typeParams) {
TypeDeclaration td = null;
if (m.get(KEY_METATYPE) instanceof TypeDeclaration) {
td = (TypeDeclaration) m.get(KEY_METATYPE);
if (td instanceof ClassOrInterface && td.getUnit().getPackage() instanceof JsonPackage) {
((JsonPackage) td.getUnit().getPackage()).load(td.getName(), typeParams);
}
}
final String tname = (String) m.get(KEY_NAME);
if ("$U".equals(tname)) {
m.put(KEY_METATYPE, unknown);
return unknown.getType();
}
if (td == null && m.containsKey("comp")) {
@SuppressWarnings("unchecked") final List<Map<String, Object>> tmaps = (List<Map<String, Object>>) m.get(KEY_TYPES);
final ArrayList<Type> types = new ArrayList<>(tmaps.size());
if ("u".equals(m.get("comp"))) {
UnionType ut = new UnionType(u2);
for (Map<String, Object> tmap : tmaps) {
types.add(getTypeFromJson(tmap, container, typeParams));
}
ut.setCaseTypes(types);
td = ut;
} else if ("i".equals(m.get("comp"))) {
IntersectionType it = new IntersectionType(u2);
for (Map<String, Object> tmap : tmaps) {
types.add(getTypeFromJson(tmap, container, typeParams));
}
it.setSatisfiedTypes(types);
td = it;
} else {
throw new IllegalArgumentException("Invalid composite type '" + m.get("comp") + "'");
}
} else if (td == null) {
final String pname = (String) m.get(KEY_PACKAGE);
if (pname == null) {
// It's a ref to a type parameter
final List<TypeParameter> containerTypeParameters;
if (container instanceof Constructor) {
containerTypeParameters = ((Generic) container.getContainer()).getTypeParameters();
} else if (container instanceof Generic) {
containerTypeParameters = container.getTypeParameters();
} else {
containerTypeParameters = null;
}
if (containerTypeParameters != null) {
for (TypeParameter typeParam : containerTypeParameters) {
if (typeParam.getName().equals(tname)) {
td = typeParam;
}
}
}
if (td == null && typeParams != null) {
for (TypeParameter typeParam : typeParams) {
if (typeParam.getName().equals(tname)) {
td = typeParam;
}
}
}
} else {
String mname = (String) m.get(KEY_MODULE);
if ("$".equals(mname)) {
mname = LANGUAGE_MODULE_NAME;
}
org.eclipse.ceylon.model.typechecker.model.Package rp;
if ("$".equals(pname) || LANGUAGE_MODULE_NAME.equals(pname)) {
// Language module package
rp = isLanguagePackage() ? this : getModule().getLanguageModule().getDirectPackage(LANGUAGE_MODULE_NAME);
} else if (mname == null) {
// local type
if (".".equals(pname)) {
rp = this;
if (container instanceof TypeDeclaration && tname.equals(container.getName())) {
td = (TypeDeclaration) container;
}
} else {
rp = getModule().getDirectPackage(pname);
}
} else {
rp = getModule().getPackage(pname);
}
if (rp == null) {
throw new CompilerErrorException("Package not found: " + pname);
}
if (rp != this && rp instanceof JsonPackage && !((JsonPackage) rp).loaded) {
((JsonPackage) rp).loadIfNecessary();
}
final boolean nested = tname.indexOf('.') > 0;
final String level1 = nested ? tname.substring(0, tname.indexOf('.')) : tname;
if (rp != null && !nested) {
Declaration d = rp.getDirectMember(tname, null, false);
if (d instanceof TypeDeclaration) {
td = (TypeDeclaration) d;
if (td.isTuple()) {
if (m.containsKey(KEY_TYPES)) {
@SuppressWarnings("unchecked") List<Map<String, Object>> elemaps = (List<Map<String, Object>>) m.get(KEY_TYPES);
ArrayList<Type> elems = new ArrayList<>(elemaps.size());
for (Map<String, Object> elem : elemaps) {
elems.add(getTypeFromJson(elem, container, typeParams));
}
Type tail = elems.get(elems.size() - 1);
if ((tail.isSequence() || tail.isSequential()) && !tail.isTuple() && !tail.isEmpty()) {
elems.remove(elems.size() - 1);
} else {
tail = null;
}
return u2.getTupleType(elems, tail, -1);
} else if (m.containsKey("count")) {
@SuppressWarnings("unchecked") Map<String, Object> elem = (Map<String, Object>) m.get(KEY_TYPE);
Type[] elems = new Type[(int) m.remove("count")];
Arrays.fill(elems, getTypeFromJson(elem, container, typeParams));
return u2.getTupleType(Arrays.asList(elems), null, -1);
}
}
} else if (d instanceof FunctionOrValue) {
td = ((FunctionOrValue) d).getTypeDeclaration();
}
}
if (td == null && rp instanceof JsonPackage) {
if (nested) {
td = ((JsonPackage) rp).loadNestedType(tname, typeParams);
} else {
td = (TypeDeclaration) ((JsonPackage) rp).load(tname, typeParams);
}
}
// Then look in the top-level declarations
if (nested && td == null) {
for (Declaration d : rp.getMembers()) {
if (d instanceof TypeDeclaration && level1.equals(d.getName())) {
td = (TypeDeclaration) d;
}
}
final String[] path = tname.split("\\.");
for (int i = 1; i < path.length; i++) {
td = (TypeDeclaration) td.getDirectMember(path[i], null, false);
}
}
}
}
// From 1.2.3 we stored type arguments in maps
final Type newType = loadTypeArguments(m, td, container, typeParams);
if (newType != null) {
return newType;
}
// This is the old pre 1.2.3 stuff
@SuppressWarnings("unchecked") final List<Map<String, Object>> modelParms = (List<Map<String, Object>>) m.get(KEY_TYPE_PARAMS);
if (td != null && modelParms != null) {
// Substitute type parameters
final HashMap<TypeParameter, Type> concretes = new HashMap<>();
HashMap<TypeParameter, SiteVariance> variances = null;
if (td.getTypeParameters().size() < modelParms.size()) {
if (td.getUnit().getPackage() == this) {
parseTypeParameters(modelParms, td, null);
}
}
final Iterator<TypeParameter> viter = td.getTypeParameters().iterator();
for (Map<String, Object> ptparm : modelParms) {
TypeParameter _cparm = viter.next();
if (ptparm.containsKey(KEY_PACKAGE) || ptparm.containsKey(KEY_TYPES)) {
// Substitute for proper type
final Type _pt = getTypeFromJson(ptparm, container, typeParams);
concretes.put(_cparm, _pt);
} else if (ptparm.containsKey(KEY_NAME) && typeParams != null) {
// Look for type parameter with same name
for (TypeParameter typeParam : typeParams) {
if (typeParam.getName().equals(ptparm.get(KEY_NAME))) {
concretes.put(_cparm, typeParam.getType());
}
}
}
Integer usv = (Integer) ptparm.get(KEY_US_VARIANCE);
if (usv != null) {
if (variances == null) {
variances = new HashMap<>();
}
variances.put(_cparm, SiteVariance.values()[usv]);
}
}
if (!concretes.isEmpty()) {
return td.getType().substitute(concretes, variances);
}
}
if (td == null) {
try {
throw new IllegalArgumentException(String.format("Couldn't find type %s::%s for %s in %s<%s> (FROM pkg %s)", m.get(KEY_PACKAGE), m.get(KEY_NAME), m.get(KEY_MODULE), m, typeParams, getNameAsString()));
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
}
return td.getType();
}
Aggregations