/******************************************************************************* * 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 * * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl * * Emilie Balland - (CWI) * * Paul Klint - Paul.Klint@cwi.nl - CWI * * Arnold Lankamp - Arnold.Lankamp@cwi.nl * * Mark Hills - Mark.Hills@cwi.nl - CWI *******************************************************************************/ package org.rascalmpl.interpreter.matching; import java.util.HashMap; import java.util.List; import java.util.Map; import org.rascalmpl.ast.Expression; import org.rascalmpl.interpreter.IEvaluatorContext; import org.rascalmpl.interpreter.env.Environment; import org.rascalmpl.interpreter.result.ResultFactory; import org.rascalmpl.interpreter.utils.Names; import org.rascalmpl.value.exceptions.FactTypeUseException; import org.rascalmpl.value.type.Type; public class TypedVariablePattern extends AbstractMatchingResult implements IVarPattern { private String name; protected org.rascalmpl.value.type.Type declaredType; private boolean anonymous = false; private boolean debug = false; protected boolean alreadyStored = false; public TypedVariablePattern(IEvaluatorContext ctx, Expression x, org.rascalmpl.value.type.Type type, org.rascalmpl.ast.Name name) { super(ctx, x); this.name = Names.name(name); this.declaredType = type; this.anonymous = Names.name(name).equals("_"); if(debug) System.err.println("AbstractPatternTypedVariabe: " + name); } public TypedVariablePattern(IEvaluatorContext ctx, Expression x, org.rascalmpl.value.type.Type type, String name) { super(ctx, x); this.name = name; this.declaredType = type; this.anonymous = name.equals("_"); if(debug) System.err.println("AbstractPatternTypedVariabe: " + name); } @Override public Type getType(Environment env, HashMap<String,IVarPattern> patternVars) { 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 name; } public boolean isAnonymous(){ return anonymous; } @Override public boolean next() { if(debug)System.err.println("AbstractTypedVariable.next"); checkInitialized(); if(!hasNext) return false; hasNext = false; if(debug) { System.err.println("Subject: " + subject + " name: " + name + " getType: "); System.err.println("AbstractTypedVariable.next: " + subject + "(type=" + subject.getType() + ") with " + declaredType + " " + name); } Type tmp; if (subject.getValue().getType().isSubtypeOf(declaredType)) { if(debug)System.err.println("matches"); try { // type checking code for formal parameters; the static type of the actual should be a sub-type of the type of the formal Map<Type, Type> bindings = new HashMap<Type,Type>(); bindings.putAll(ctx.getCurrentEnvt().getTypeBindings()); declaredType.match(subject.getType(), bindings); tmp = declaredType.instantiate(bindings); if (tmp != declaredType) { ctx.getCurrentEnvt().storeTypeBindings(bindings); } } catch (FactTypeUseException e) { // however, in normal matching (not formal parameters) we allow the static type to be a strict super-type, as long as the dynamic type is a sub-type of the pattern we succeed! tmp = declaredType; } if (anonymous) { return true; } ctx.getCurrentEnvt().declareAndStoreInferredInnerScopeVariable(name, ResultFactory.makeResult(tmp, subject.getValue(), ctx)); this.alreadyStored = true; return true; } if(debug)System.err.println("no match"); return false; } @Override public String toString(){ return declaredType + " " + name /* + " => " + subject */; } @Override public boolean isVarIntroducing() { return true; } @Override public String name() { return getName(); } @Override public Type getType() { return declaredType; } public boolean bindingInstance() { return this.alreadyStored; } }