package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.codegen.references.IVal; import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.exceptions.MatchException; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.THashSet; import gnu.trove.set.hash.TIntHashSet; public class EAsPattern extends Expression { public Variable var; public EVar eVar; public Expression pattern; public EAsPattern(EVar eVar, Expression pattern) { this.eVar = eVar; this.pattern = pattern; } public EAsPattern(Variable var, Expression pattern) { this.var = var; this.pattern = pattern; } public Variable getVariable() { return var; } public Expression getPattern() { return pattern; } @Override public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { int id = allVars.get(var); if(id >= 0) vars.add(id); pattern.collectVars(allVars, vars); } @Override public void collectFreeVariables(THashSet vars) { throw new InternalCompilerError(location, "Cannot collect free variables for a pattern."); } @Override public void removeFreeVariables(THashSet vars) { vars.remove(var); pattern.removeFreeVariables(vars); } @Override public Expression simplify(SimplificationContext context) { pattern = pattern.simplify(context); return this; } @Override public Expression resolve(TranslationContext context) { context.getErrorLog().log(location, "As binding (@) can be used only in patterns."); return this; } @Override public Expression resolveAsPattern(TranslationContext context) { var = context.newVariable(eVar.name); pattern = pattern.resolveAsPattern(context); return this; } @Override protected void updateType() throws MatchException { setType(pattern.getType()); } @Override public IVal toVal(CompilationContext context, CodeWriter w) { throw new InternalCompilerError("EAsPattern allowed only in patterns."); } @Override public Expression inferType(TypingContext context) { pattern = pattern.inferType(context); var.setType(pattern.getType()); return this; } @Override public Expression checkBasicType(TypingContext context, Type requiredType) { pattern = pattern.checkBasicType(context, requiredType); var.setType(pattern.getType()); return this; } @Override public Expression replace(ReplaceContext context) { if(!context.inPattern) throw new IllegalStateException(); Variable newVariable = new Variable(var.name); newVariable.setType(var.getType().replace(context.tvarMap)); context.varMap.put(var, new EVariable(newVariable)); EAsPattern result = new EAsPattern(eVar, pattern.replace(context)); result.var = newVariable; return result; } @Override public void setLocationDeep(long loc) { if(location == Locations.NO_LOCATION) { location = loc; pattern.setLocationDeep(loc); if(eVar != null) eVar.setLocationDeep(loc); } } @Override public void accept(ExpressionVisitor visitor) { visitor.visit(this); } @Override public Expression accept(ExpressionTransformer transformer) { return transformer.transform(this); } }