/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*******************************************************************************/
package org.rascalmpl.interpreter.types;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.ISetWriter;
import org.rascalmpl.value.IValueFactory;
import org.rascalmpl.value.exceptions.FactTypeUseException;
import org.rascalmpl.value.exceptions.UndeclaredAnnotationException;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeFactory;
import org.rascalmpl.value.type.TypeFactory.TypeReifier;
import org.rascalmpl.value.type.TypeStore;
/**
* A reified type is the type of a value that represents a type. It is parametrized by the type
* it represents.
*
* For example, the '#int' expression produces the 'type(int(),())' value which is of type 'type[int]'
*/
public class ReifiedType extends RascalType {
private final Type arg;
public ReifiedType(Type arg) {
this.arg = arg;
}
public static class Reifier implements TypeReifier {
@Override
public Type getSymbolConstructorType() {
return symbols().typeSymbolConstructor("reified", symbols().symbolADT(), "symbol");
}
@Override
public Type fromSymbol(IConstructor symbol, TypeStore store,
Function<IConstructor, Set<IConstructor>> grammar) {
return RTF.reifiedType(symbols().fromSymbol((IConstructor) symbol.get("symbol"), store, grammar));
}
@Override
public IConstructor toSymbol(Type type, IValueFactory vf, TypeStore store, ISetWriter grammar, Set<IConstructor> done) {
return vf.constructor(getSymbolConstructorType(), type.getTypeParameters().getFieldType(0).asSymbol(vf, store, grammar, done));
}
@Override
public void asProductions(Type type, IValueFactory vf, TypeStore store, ISetWriter grammar,
Set<IConstructor> done) {
((ReifiedType) type).arg.asProductions(vf, store, grammar, done);
}
@Override
public boolean isRecursive() {
return true;
}
@Override
public Type randomInstance(Supplier<Type> next, TypeStore store, Random rnd) {
return RascalTypeFactory.getInstance().reifiedType(next.get());
}
}
@Override
public TypeReifier getTypeReifier() {
return new Reifier();
}
@Override
public Type asAbstractDataType() {
return getTypeReifier().symbols().symbolADT();
}
@Override
public boolean isReified() {
return true;
}
@Override
public String getName() {
return "type";
}
@Override
public boolean hasField(String fieldName) {
return fieldName.equals("symbol") || fieldName.equals("definitions");
}
@Override
public boolean hasKeywordField(String fieldName, TypeStore store) {
return false;
}
@Override
public boolean isParameterized() {
return true;
}
@Override
public boolean isOpen() {
return arg.isOpen();
}
@Override
public <T, E extends Throwable> T accept(IRascalTypeVisitor<T, E> visitor) throws E {
return visitor.visitReified(this);
}
@Override
protected boolean isSupertypeOf(RascalType type) {
return type.isSubtypeOfReified(this);
}
@Override
protected Type lub(RascalType type) {
return type.lubWithReified(this);
}
@Override
protected Type glb(RascalType type) {
return type.glbWithReified(this);
}
@Override
public Type getTypeParameters() {
return TypeFactory.getInstance().tupleType(arg);
}
@Override
protected boolean isSubtypeOfNode(Type type) {
return true;
}
@Override
protected boolean isSubtypeOfReified(RascalType type) {
return arg.isSubtypeOf(((ReifiedType) type).arg);
}
@Override
protected Type lubWithNode(Type type) {
return type;
}
@Override
protected Type lubWithReified(RascalType type) {
return RascalTypeFactory.getInstance().reifiedType(arg.lub(((ReifiedType) type).arg));
}
@Override
protected Type glbWithNode(Type type) {
return this;
}
@Override
protected Type glbWithReified(RascalType type) {
return RascalTypeFactory.getInstance().reifiedType(arg.glb(((ReifiedType) type).arg));
}
@Override
public boolean match(Type matched, Map<Type, Type> bindings)
throws FactTypeUseException {
if (matched instanceof ReifiedType) {
return super.match(matched, bindings)
&& arg.match(((ReifiedType) matched).arg, bindings);
}
else if (matched.isBottom()) {
return arg.match(matched, bindings);
}
else {
return false;
}
}
@Override
public Type instantiate(Map<Type, Type> bindings) {
return RascalTypeFactory.getInstance().reifiedType(arg.instantiate(bindings));
}
@Override
public String toString() {
return "type[" + arg.toString() + "]";
}
@Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if (obj.getClass() == getClass()) {
return arg.equals(((ReifiedType) obj).arg);
}
return false;
}
@Override
public int hashCode() {
return 2331 + arg.hashCode();
}
@Override
public boolean declaresAnnotation(TypeStore store, String label) {
return false;
}
@Override
public Type getAnnotationType(TypeStore store, String label) throws FactTypeUseException {
throw new UndeclaredAnnotationException(this, label);
}
}