private void determineTypesUpto(int end) { Type[] environment = environments[0]; for (int i = position; i < end; ++i) { Code code = stmts.get(i).code; if (code instanceof Code.Label) { Code.Label label = (Code.Label) code; Type[] nEnv = cache.get(label.label); environment = join(environment, nEnv); } else if (code instanceof Code.AbstractAssignable) { Code.AbstractAssignable c = (Code.AbstractAssignable) code; environment = Arrays.copyOf(environment, environment.length); environment[c.target] = c.assignedType(); } else if (code instanceof Code.Goto) { Code.Goto gto = (Code.Goto) code; cache.put(gto.target, environment); environment = null; } else if (code instanceof Code.If) { Code.If gto = (Code.If) code; cache.put(gto.target, environment); } else if (code instanceof Code.IfIs) { Code.IfIs gto = (Code.IfIs) code; Type[] trueEnv = Arrays.copyOf(environment, environment.length); trueEnv[gto.operand] = Type.intersect(trueEnv[gto.operand], gto.rightOperand); cache.put(gto.target, trueEnv); environment[gto.operand] = Type.intersect(trueEnv[gto.operand], Type.Negation(gto.rightOperand)); } else if (code instanceof Code.Switch) { Code.Switch sw = (Code.Switch) code; for (Pair<Constant, String> c : sw.branches) { cache.put(c.second(), environment); } cache.put(sw.defaultTarget, environment); } else if (code instanceof Code.ForAll) { // FIXME: what this need to do is update the type for the // index variable, and then invalidate it afterwards. throw new RuntimeException("need to implement for-all loop!"); } else if (code instanceof Code.Return || code instanceof Code.Throw) { environment = null; } environments[i] = environment; } }
private SemanticType propagate( Expr.FunCall e, HashMap<String, SemanticType> environment, HashSet<String> generics, WyalFile.Context context) { SemanticType.Function fnType; try { Pair<NameID, SemanticType.Function> p = builder.resolveAsFunctionType(e.name, context); fnType = p.second(); } catch (ResolveError re) { syntaxError( "cannot resolve as function or definition call", context.file().filename(), e, re); return null; } SemanticType[] fn_generics = fnType.generics(); if (fn_generics.length != e.generics.length) { // could resolve this with inference in the future. syntaxError( "incorrect number of generic arguments provided (got " + e.generics.length + ", required " + fn_generics.length + ")", context.file().filename(), e); } SemanticType argument = propagate(e.operand, environment, generics, context); HashMap<String, SemanticType> binding = new HashMap<String, SemanticType>(); for (int i = 0; i != e.generics.length; ++i) { SemanticType.Var gv = (SemanticType.Var) fn_generics[i]; binding.put(gv.name(), builder.convert(e.generics[i], generics, context)); } fnType = (SemanticType.Function) fnType.substitute(binding); checkIsSubtype(fnType.from(), argument, e.operand); return fnType; }