Program: 27799
Project: 27799
Buggy source:
/** 
 * For now, we won't emit any warnings bwd.
 */
private EnvTypePair analyzeExprBwd(Node expr,TypeEnv outEnv,JSType requiredType){
  Preconditions.checkArgument(requiredType != null && !requiredType.isBottom());
  int exprKind=expr.getType();
switch (exprKind) {
case Token.EMPTY:
    return new EnvTypePair(outEnv,JSType.UNKNOWN);
case Token.FUNCTION:
{
    String fnName=symbolTable.getFunInternalName(expr);
    return new EnvTypePair(outEnv,envGetType(outEnv,fnName));
  }
case Token.FALSE:
case Token.NULL:
case Token.NUMBER:
case Token.STRING:
case Token.TRUE:
return new EnvTypePair(outEnv,scalarValueToType(exprKind));
case Token.OBJECTLIT:
{
JSType result=JSType.TOP_OBJECT;
TypeEnv env=outEnv;
for (Node key=expr.getLastChild(); key != null; key=expr.getChildBefore(key)) {
  String pname=NodeUtil.getObjectLitKeyName(key);
  JSType reqPtype=requiredType.mayHaveProp(pname) ? requiredType.getProp(pname) : JSType.TOP;
  EnvTypePair pair=analyzeExprBwd(key.getLastChild(),env,reqPtype);
  result=result.withProperty(pname,pair.type);
  env=pair.env;
}
return new EnvTypePair(env,result);
}
case Token.THIS:
{
if (!currentScope.hasThis()) {
return new EnvTypePair(outEnv,JSType.UNKNOWN);
}
JSType thisType=currentScope.getDeclaredTypeOf("String_Node_Str");
return new EnvTypePair(outEnv,thisType);
}
case Token.NAME:
{
String varName=expr.getQualifiedName();
if (varName.equals("String_Node_Str")) {
return new EnvTypePair(outEnv,JSType.UNDEFINED);
}
JSType inferredType=envGetType(outEnv,varName);
if (inferredType == null) {
inferredType=JSType.TOP;
}
JSType preciseType=inferredType.specialize(requiredType);
if (currentScope.isUndeclaredFormal(varName) && requiredType.hasNonScalar()) {
preciseType=preciseType.withLoose();
}
if (!preciseType.isInhabitable()) {
JSType declType=currentScope.getDeclaredTypeOf(varName);
preciseType=declType == null ? requiredType : declType;
}
return EnvTypePair.addBinding(outEnv,varName,preciseType);
}
case Token.INC:
case Token.DEC:
case Token.BITNOT:
case Token.POS:
case Token.NEG:
return analyzeExprBwd(expr.getFirstChild(),outEnv,JSType.NUMBER);
case Token.TYPEOF:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=JSType.STRING;
return pair;
}
case Token.INSTANCEOF:
{
TypeEnv env=analyzeExprBwd(expr.getLastChild(),outEnv,JSType.topFunction()).env;
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),env);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.BITOR:
case Token.BITAND:
case Token.BITXOR:
case Token.DIV:
case Token.LSH:
case Token.MOD:
case Token.MUL:
case Token.RSH:
case Token.SUB:
case Token.URSH:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
TypeEnv rhsEnv=analyzeExprBwd(rhs,outEnv,JSType.NUMBER).env;
EnvTypePair pair=analyzeExprBwd(lhs,rhsEnv,JSType.NUMBER);
pair.type=JSType.NUMBER;
return pair;
}
case Token.ADD:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair rhsPair=analyzeExprBwd(rhs,outEnv,JSType.NUM_OR_STR);
EnvTypePair lhsPair=analyzeExprBwd(lhs,rhsPair.env,JSType.NUM_OR_STR);
lhsPair.type=JSType.plus(lhsPair.type,rhsPair.type);
return lhsPair;
}
case Token.OR:
case Token.AND:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair rhsPair=analyzeExprBwd(rhs,outEnv);
EnvTypePair lhsPair=analyzeExprBwd(lhs,rhsPair.env);
lhsPair.type=JSType.join(rhsPair.type,lhsPair.type);
return lhsPair;
}
case Token.SHEQ:
case Token.SHNE:
case Token.EQ:
case Token.NE:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
TypeEnv rhsEnv=analyzeExprBwd(rhs,outEnv).env;
EnvTypePair pair=analyzeExprBwd(lhs,rhsEnv);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.LT:
case Token.GT:
case Token.LE:
case Token.GE:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair rhsPair=analyzeExprBwd(rhs,outEnv);
EnvTypePair lhsPair=analyzeExprBwd(lhs,rhsPair.env);
JSType meetType=JSType.meet(lhsPair.type,rhsPair.type);
if (meetType.isBottom()) {
lhsPair.type=JSType.BOOLEAN;
return lhsPair;
}
rhsPair=analyzeExprBwd(rhs,outEnv,meetType);
lhsPair=analyzeExprBwd(lhs,rhsPair.env,meetType);
lhsPair.type=JSType.BOOLEAN;
return lhsPair;
}
case Token.ASSIGN:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
LValueResult lvalue=analyzeLValueBwd(lhs,outEnv,requiredType,true);
TypeEnv slicedEnv=lvalue.env;
JSType rhsReqType=specializeWithCorrection(lvalue.type,requiredType);
EnvTypePair pair=analyzeExprBwd(rhs,slicedEnv,rhsReqType);
pair.env=analyzeLValueBwd(lhs,pair.env,requiredType,true).env;
return pair;
}
case Token.ASSIGN_ADD:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
JSType lhsReqType=specializeWithCorrection(requiredType,JSType.NUM_OR_STR);
LValueResult lvalue=analyzeLValueBwd(lhs,outEnv,lhsReqType,false);
JSType rhsReqType=lvalue.type.equals(JSType.NUMBER) ? JSType.NUMBER : JSType.NUM_OR_STR;
EnvTypePair pair=analyzeExprBwd(rhs,outEnv,rhsReqType);
pair.env=analyzeLValueBwd(lhs,pair.env,lhsReqType,false).env;
return pair;
}
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
case Token.ASSIGN_SUB:
case Token.ASSIGN_MUL:
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair pair=analyzeExprBwd(rhs,outEnv,JSType.NUMBER);
LValueResult lvalue=analyzeLValueBwd(lhs,pair.env,JSType.NUMBER,false);
return new EnvTypePair(lvalue.env,JSType.NUMBER);
}
case Token.GETPROP:
{
Preconditions.checkState(!NodeUtil.isAssignmentOp(expr.getParent()) || !NodeUtil.isLValue(expr));
return analyzePropAccessBwd(expr.getFirstChild(),expr.getLastChild().getString(),outEnv,requiredType);
}
case Token.HOOK:
{
Node cond=expr.getFirstChild();
Node thenBranch=cond.getNext();
Node elseBranch=thenBranch.getNext();
EnvTypePair thenPair=analyzeExprBwd(thenBranch,outEnv,requiredType);
EnvTypePair elsePair=analyzeExprBwd(elseBranch,outEnv,requiredType);
return analyzeExprBwd(cond,TypeEnv.join(thenPair.env,elsePair.env));
}
case Token.CALL:
case Token.NEW:
{
Node callee=expr.getFirstChild();
JSType calleeTypeGeneral=analyzeExprBwd(callee,outEnv,JSType.topFunction()).type;
FunctionType funType=calleeTypeGeneral.getFunType();
if (funType == null) {
return new EnvTypePair(outEnv,requiredType);
}
 else if (funType.isLoose()) {
return analyzeLooseCallNodeBwd(expr,outEnv,requiredType);
}
 else if (expr.isCall() && funType.isConstructor() || expr.isNew() && !funType.isConstructor()) {
return new EnvTypePair(outEnv,requiredType);
}
 else if (funType.isTopFunction()) {
return new EnvTypePair(outEnv,requiredType);
}
int arity=funType.getMaxArity();
TypeEnv tmpEnv=outEnv;
for (int i=expr.getChildCount() - 2; i >= 0; i--) {
JSType formalType=i < arity ? funType.getFormalType(i) : JSType.TOP;
if (formalType.isBottom()) {
formalType=JSType.TOP;
}
Node arg=expr.getChildAtIndex(i + 1);
tmpEnv=analyzeExprBwd(arg,tmpEnv,formalType).env;
}
if (callee.isName()) {
String calleeName=callee.getQualifiedName();
if (currentScope.isKnownFunction(calleeName)) {
if (currentScope.isLocalFunDef(calleeName)) {
tmpEnv=collectTypesForFreeVarsBwd(callee,tmpEnv);
}
 else if (expr.isCall()) {
Scope s=currentScope.getScope(calleeName);
JSType expectedRetType=JSType.TOP;
if (s.getDeclaredType().getReturnType() == null) {
expectedRetType=requiredType;
}
println("String_Node_Str",calleeName,"String_Node_Str",expectedRetType);
DeferredCheck dc=new DeferredCheck(expr,currentScope,s);
dc.updateReturn(expectedRetType);
deferredChecks.put(expr,dc);
}
}
}
return new EnvTypePair(tmpEnv,funType.getReturnType());
}
case Token.COMMA:
{
EnvTypePair pair=analyzeExprBwd(expr.getLastChild(),outEnv,requiredType);
pair.env=analyzeExprBwd(expr.getFirstChild(),pair.env).env;
return pair;
}
case Token.NOT:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=pair.type.negate();
return pair;
}
case Token.GETELEM:
{
Node receiver=expr.getFirstChild();
Node index=expr.getLastChild();
if (index.isString()) {
return analyzePropAccessBwd(receiver,index.getString(),outEnv,requiredType);
}
EnvTypePair pair=analyzeExprBwd(index,outEnv);
pair=analyzeExprBwd(receiver,pair.env,JSType.TOP_OBJECT);
pair.type=requiredType;
return pair;
}
case Token.VOID:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=JSType.UNDEFINED;
return pair;
}
case Token.IN:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair pair=analyzeExprBwd(rhs,outEnv,JSType.TOP_OBJECT);
pair=analyzeExprBwd(lhs,pair.env,JSType.NUM_OR_STR);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.DELPROP:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.VAR:
{
Node vdecl=expr.getFirstChild();
String name=vdecl.getQualifiedName();
Node rhs=vdecl.getFirstChild();
TypeEnv env=outEnv;
if (rhs != null) {
env=analyzeExprBwd(rhs,outEnv).env;
}
return new EnvTypePair(envPutType(env,name,JSType.UNKNOWN),JSType.UNKNOWN);
}
case Token.REGEXP:
return new EnvTypePair(outEnv,regexpType);
case Token.ARRAYLIT:
TypeEnv env=outEnv;
for (int i=expr.getChildCount() - 1; i >= 0; i--) {
Node arrayElm=expr.getChildAtIndex(i);
env=analyzeExprBwd(arrayElm,env).env;
}
return new EnvTypePair(env,arrayType);
default :
throw new RuntimeException("String_Node_Str" + Token.name(expr.getType()) + "String_Node_Str"+ expr.getParent());
}
}

Fixed version (ground truth):
/** 
 * For now, we won't emit any warnings bwd.
 */
private EnvTypePair analyzeExprBwd(Node expr,TypeEnv outEnv,JSType requiredType){
  Preconditions.checkArgument(requiredType != null && !requiredType.isBottom());
  int exprKind=expr.getType();
switch (exprKind) {
case Token.EMPTY:
    return new EnvTypePair(outEnv,JSType.UNKNOWN);
case Token.FUNCTION:
{
    String fnName=symbolTable.getFunInternalName(expr);
    return new EnvTypePair(outEnv,envGetType(outEnv,fnName));
  }
case Token.FALSE:
case Token.NULL:
case Token.NUMBER:
case Token.STRING:
case Token.TRUE:
return new EnvTypePair(outEnv,scalarValueToType(exprKind));
case Token.OBJECTLIT:
{
JSType result=JSType.TOP_OBJECT;
TypeEnv env=outEnv;
for (Node key=expr.getLastChild(); key != null; key=expr.getChildBefore(key)) {
  String pname=NodeUtil.getObjectLitKeyName(key);
  JSType reqPtype=requiredType.mayHaveProp(pname) ? requiredType.getProp(pname) : JSType.TOP;
  EnvTypePair pair=analyzeExprBwd(key.getLastChild(),env,reqPtype);
  result=result.withProperty(pname,pair.type);
  env=pair.env;
}
return new EnvTypePair(env,result);
}
case Token.THIS:
{
if (!currentScope.hasThis()) {
return new EnvTypePair(outEnv,JSType.UNKNOWN);
}
JSType thisType=currentScope.getDeclaredTypeOf("String_Node_Str");
return new EnvTypePair(outEnv,thisType);
}
case Token.NAME:
{
String varName=expr.getQualifiedName();
if (varName.equals("String_Node_Str")) {
return new EnvTypePair(outEnv,JSType.UNDEFINED);
}
JSType inferredType=envGetType(outEnv,varName);
if (inferredType == null) {
inferredType=JSType.TOP;
}
JSType preciseType=inferredType.specialize(requiredType);
if (currentScope.isUndeclaredFormal(varName) && requiredType.hasNonScalar()) {
preciseType=preciseType.withLoose();
}
if (!preciseType.isInhabitable()) {
JSType declType=currentScope.getDeclaredTypeOf(varName);
preciseType=declType == null ? requiredType : declType;
}
return EnvTypePair.addBinding(outEnv,varName,preciseType);
}
case Token.INC:
case Token.DEC:
case Token.BITNOT:
case Token.POS:
case Token.NEG:
return analyzeExprBwd(expr.getFirstChild(),outEnv,JSType.NUMBER);
case Token.TYPEOF:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=JSType.STRING;
return pair;
}
case Token.INSTANCEOF:
{
TypeEnv env=analyzeExprBwd(expr.getLastChild(),outEnv,JSType.topFunction()).env;
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),env);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.BITOR:
case Token.BITAND:
case Token.BITXOR:
case Token.DIV:
case Token.LSH:
case Token.MOD:
case Token.MUL:
case Token.RSH:
case Token.SUB:
case Token.URSH:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
TypeEnv rhsEnv=analyzeExprBwd(rhs,outEnv,JSType.NUMBER).env;
EnvTypePair pair=analyzeExprBwd(lhs,rhsEnv,JSType.NUMBER);
pair.type=JSType.NUMBER;
return pair;
}
case Token.ADD:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair rhsPair=analyzeExprBwd(rhs,outEnv,JSType.NUM_OR_STR);
EnvTypePair lhsPair=analyzeExprBwd(lhs,rhsPair.env,JSType.NUM_OR_STR);
lhsPair.type=JSType.plus(lhsPair.type,rhsPair.type);
return lhsPair;
}
case Token.OR:
case Token.AND:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair rhsPair=analyzeExprBwd(rhs,outEnv);
EnvTypePair lhsPair=analyzeExprBwd(lhs,rhsPair.env);
lhsPair.type=JSType.join(rhsPair.type,lhsPair.type);
return lhsPair;
}
case Token.SHEQ:
case Token.SHNE:
case Token.EQ:
case Token.NE:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
TypeEnv rhsEnv=analyzeExprBwd(rhs,outEnv).env;
EnvTypePair pair=analyzeExprBwd(lhs,rhsEnv);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.LT:
case Token.GT:
case Token.LE:
case Token.GE:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair rhsPair=analyzeExprBwd(rhs,outEnv);
EnvTypePair lhsPair=analyzeExprBwd(lhs,rhsPair.env);
JSType meetType=JSType.meet(lhsPair.type,rhsPair.type);
if (meetType.isBottom()) {
lhsPair.type=JSType.BOOLEAN;
return lhsPair;
}
rhsPair=analyzeExprBwd(rhs,outEnv,meetType);
lhsPair=analyzeExprBwd(lhs,rhsPair.env,meetType);
lhsPair.type=JSType.BOOLEAN;
return lhsPair;
}
case Token.ASSIGN:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
LValueResult lvalue=analyzeLValueBwd(lhs,outEnv,requiredType,true);
TypeEnv slicedEnv=lvalue.env;
JSType rhsReqType=specializeWithCorrection(lvalue.type,requiredType);
EnvTypePair pair=analyzeExprBwd(rhs,slicedEnv,rhsReqType);
pair.env=analyzeLValueBwd(lhs,pair.env,requiredType,true).env;
return pair;
}
case Token.ASSIGN_ADD:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
JSType lhsReqType=specializeWithCorrection(requiredType,JSType.NUM_OR_STR);
LValueResult lvalue=analyzeLValueBwd(lhs,outEnv,lhsReqType,false);
JSType rhsReqType=lvalue.type.equals(JSType.NUMBER) ? JSType.NUMBER : JSType.NUM_OR_STR;
EnvTypePair pair=analyzeExprBwd(rhs,outEnv,rhsReqType);
pair.env=analyzeLValueBwd(lhs,pair.env,lhsReqType,false).env;
return pair;
}
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
case Token.ASSIGN_SUB:
case Token.ASSIGN_MUL:
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair pair=analyzeExprBwd(rhs,outEnv,JSType.NUMBER);
LValueResult lvalue=analyzeLValueBwd(lhs,pair.env,JSType.NUMBER,false);
return new EnvTypePair(lvalue.env,JSType.NUMBER);
}
case Token.GETPROP:
{
Preconditions.checkState(!NodeUtil.isAssignmentOp(expr.getParent()) || !NodeUtil.isLValue(expr));
return analyzePropAccessBwd(expr.getFirstChild(),expr.getLastChild().getString(),outEnv,requiredType);
}
case Token.HOOK:
{
Node cond=expr.getFirstChild();
Node thenBranch=cond.getNext();
Node elseBranch=thenBranch.getNext();
EnvTypePair thenPair=analyzeExprBwd(thenBranch,outEnv,requiredType);
EnvTypePair elsePair=analyzeExprBwd(elseBranch,outEnv,requiredType);
return analyzeExprBwd(cond,TypeEnv.join(thenPair.env,elsePair.env));
}
case Token.CALL:
case Token.NEW:
{
Node callee=expr.getFirstChild();
JSType calleeTypeGeneral=analyzeExprBwd(callee,outEnv,JSType.topFunction()).type;
FunctionType funType=calleeTypeGeneral.getFunType();
if (funType == null) {
return new EnvTypePair(outEnv,requiredType);
}
 else if (funType.isLoose()) {
return analyzeLooseCallNodeBwd(expr,outEnv,requiredType);
}
 else if (expr.isCall() && funType.isConstructor() || expr.isNew() && !funType.isConstructor()) {
return new EnvTypePair(outEnv,requiredType);
}
 else if (funType.isTopFunction()) {
return new EnvTypePair(outEnv,requiredType);
}
int arity=funType.getMaxArity();
TypeEnv tmpEnv=outEnv;
for (int i=expr.getChildCount() - 2; i >= 0; i--) {
JSType formalType=i < arity ? funType.getFormalType(i) : JSType.TOP;
if (formalType.isBottom()) {
formalType=JSType.TOP;
}
Node arg=expr.getChildAtIndex(i + 1);
tmpEnv=analyzeExprBwd(arg,tmpEnv,formalType).env;
}
if (callee.isName()) {
String calleeName=callee.getQualifiedName();
if (currentScope.isKnownFunction(calleeName)) {
if (currentScope.isLocalFunDef(calleeName)) {
tmpEnv=collectTypesForFreeVarsBwd(callee,tmpEnv);
}
 else if (expr.isCall()) {
Scope s=currentScope.getScope(calleeName);
JSType expectedRetType=JSType.TOP;
if (s.getDeclaredType().getReturnType() == null) {
expectedRetType=requiredType;
}
println("String_Node_Str",calleeName,"String_Node_Str",expectedRetType);
DeferredCheck dc=new DeferredCheck(expr,currentScope,s);
dc.updateReturn(expectedRetType);
deferredChecks.put(expr,dc);
}
}
}
return new EnvTypePair(tmpEnv,funType.getReturnType());
}
case Token.COMMA:
{
EnvTypePair pair=analyzeExprBwd(expr.getLastChild(),outEnv,requiredType);
pair.env=analyzeExprBwd(expr.getFirstChild(),pair.env).env;
return pair;
}
case Token.NOT:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=pair.type.negate();
return pair;
}
case Token.GETELEM:
{
Node receiver=expr.getFirstChild();
Node index=expr.getLastChild();
if (index.isString()) {
return analyzePropAccessBwd(receiver,index.getString(),outEnv,requiredType);
}
EnvTypePair pair=analyzeExprBwd(index,outEnv);
pair=analyzeExprBwd(receiver,pair.env,JSType.TOP_OBJECT);
pair.type=requiredType;
return pair;
}
case Token.VOID:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=JSType.UNDEFINED;
return pair;
}
case Token.IN:
{
Node lhs=expr.getFirstChild();
Node rhs=expr.getLastChild();
EnvTypePair pair=analyzeExprBwd(rhs,outEnv,JSType.TOP_OBJECT);
pair=analyzeExprBwd(lhs,pair.env,JSType.NUM_OR_STR);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.DELPROP:
{
EnvTypePair pair=analyzeExprBwd(expr.getFirstChild(),outEnv);
pair.type=JSType.BOOLEAN;
return pair;
}
case Token.VAR:
{
Node vdecl=expr.getFirstChild();
String name=vdecl.getQualifiedName();
Preconditions.checkState(!vdecl.hasChildren());
return new EnvTypePair(envPutType(outEnv,name,JSType.UNKNOWN),JSType.UNKNOWN);
}
case Token.REGEXP:
return new EnvTypePair(outEnv,regexpType);
case Token.ARRAYLIT:
TypeEnv env=outEnv;
for (int i=expr.getChildCount() - 1; i >= 0; i--) {
Node arrayElm=expr.getChildAtIndex(i);
env=analyzeExprBwd(arrayElm,env).env;
}
return new EnvTypePair(env,arrayType);
default :
throw new RuntimeException("String_Node_Str" + Token.name(expr.getType()) + "String_Node_Str"+ expr.getParent());
}
}