/*******************************************************************************
* 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
* * Emilie Balland - (CWI)
* * Mark Hills - Mark.Hills@cwi.nl (CWI)
* * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.matching;
import java.util.HashMap;
import java.util.List;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.rascalmpl.ast.Expression;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.staticErrors.RedeclaredVariable;
import org.rascalmpl.interpreter.utils.Names;
public class QualifiedNamePattern extends AbstractMatchingResult implements IVarPattern {
protected org.rascalmpl.ast.QualifiedName name;
protected Type declaredType;
protected boolean anonymous = false;
protected boolean debug = false;
protected boolean iWroteItMySelf;
public QualifiedNamePattern(IEvaluatorContext ctx, Expression x, org.rascalmpl.ast.QualifiedName name){
super(ctx, x);
this.name = name;
if(debug)System.err.println("QualifiedNamePattern: " + name);
this.anonymous = getName().equals("_");
Environment env = ctx.getCurrentEnvt();
// Look for this variable while we are constructing this pattern
if(anonymous) {
declaredType = TypeFactory.getInstance().valueType();
} else {
Result<IValue> varRes = env.getSimpleVariable(name);
if (varRes == null || varRes.getType() == null) {
declaredType = TypeFactory.getInstance().valueType();
} else {
declaredType = varRes.getType();
}
}
iWroteItMySelf = false;
}
public QualifiedNamePattern(IEvaluatorContext ctx){
super(ctx, null);
this.anonymous = true;
declaredType = TypeFactory.getInstance().valueType();
iWroteItMySelf = false;
}
@Override
public void initMatch(Result<IValue> subject) {
super.initMatch(subject);
// do not reinit iWroteItMyself!
}
@Override
public Type getType(Environment env, HashMap<String,IVarPattern> patternVars) {
if (anonymous) {
return declaredType;
}
if(patternVars != null && patternVars.containsKey(name)){
Type ot = patternVars.get(name).getType();
if(ot.compareTo(declaredType) < 0)
declaredType = ot;
}
return declaredType;
}
@Override
public List<IVarPattern> getVariables(){
java.util.LinkedList<IVarPattern> res = new java.util.LinkedList<IVarPattern>();
res.addFirst(this);
return res;
}
public String getName(){
return ((org.rascalmpl.semantics.dynamic.QualifiedName.Default) name).lastName();
}
public boolean isAnonymous(){
return anonymous;
}
@Override
public boolean next(){
checkInitialized();
if(!hasNext) {
return false;
}
hasNext = false;
if (debug) System.err.println("AbstractPatternQualifiedName.match: " + name);
// Anonymous variables matches always
if (anonymous) {
return true;
}
if (iWroteItMySelf) {
// overwrite a previous binding
ctx.getCurrentEnvt().storeVariable(name, subject);
return true;
}
// either bind the variable or check for equality
Result<IValue> varRes = ctx.getCurrentEnvt().getSimpleVariable(name);
if (varRes == null) {
// inferred declaration
declaredType = subject.getType();
if (!ctx.getCurrentEnvt().declareVariable(declaredType, getName())) {
throw new RedeclaredVariable(getName(), ctx.getCurrentAST());
}
ctx.getCurrentEnvt().storeVariable(name, subject);
iWroteItMySelf = true;
return true;
}
else if (varRes.getValue() == null) {
declaredType = varRes.getType();
if (!ctx.getCurrentEnvt().declareVariable(declaredType, getName())) {
throw new RedeclaredVariable(getName(), ctx.getCurrentAST());
}
ctx.getCurrentEnvt().storeVariable(name, subject);
iWroteItMySelf = true;
return true;
}
else {
// equality check
if(debug)System.err.printf("subject.getTYpe() = %s, varRes.getType() = %s\n", subject.getValue().getType(), varRes.getType());
if (subject.getValue().getType().isSubtypeOf(varRes.getType())) {
if(debug) {
System.err.println("returns " + subject.equals(varRes));
}
// iWroteItMySelf = false;
return subject.equals(varRes).isTrue();
}
return false;
}
}
@Override
public String toString(){
return Names.fullName(name);
}
public boolean bindingInstance() {
return iWroteItMySelf;
}
@Override
public boolean isVarIntroducing() {
return bindingInstance();
}
@Override
public String name() {
return getName();
}
@Override
public Type getType() {
return declaredType;
}
@Override
public void updateType(Type type) {
declaredType = type;
}
}