use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeEnumObjLitFwd.
private EnvTypePair analyzeEnumObjLitFwd(Node objLit, TypeEnv inEnv, JSType requiredType) {
// so we ignore them here.
if (objLit.getFirstChild() == null) {
return new EnvTypePair(inEnv, requiredType);
}
String pname = NodeUtil.getObjectLitKeyName(objLit.getFirstChild());
JSType enumeratedType = requiredType.getProp(new QualifiedName(pname)).getEnumeratedTypeOfEnumElement();
if (enumeratedType == null) {
// enumeratedType is null only if there is some other type error
return new EnvTypePair(inEnv, requiredType);
}
TypeEnv env = inEnv;
for (Node prop : objLit.children()) {
EnvTypePair pair = analyzeExprFwd(prop, env, enumeratedType);
if (!pair.type.isSubtypeOf(enumeratedType)) {
warnings.add(JSError.make(prop, INVALID_OBJLIT_PROPERTY_TYPE, errorMsgWithTypeDiff(enumeratedType, pair.type)));
}
env = pair.env;
}
return new EnvTypePair(env, requiredType);
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeFunctionBwd.
private void analyzeFunctionBwd(NTIWorkset workset) {
for (DiGraphNode<Node, ControlFlowGraph.Branch> dn : workset.backward()) {
Node n = dn.getValue();
TypeEnv outEnv = checkNotNull(getOutEnv(dn));
TypeEnv inEnv;
println("\tBWD Statment: ", n);
println("\t\toutEnv: ", outEnv);
switch(n.getToken()) {
case EXPR_RESULT:
inEnv = analyzeExprBwd(n.getFirstChild(), outEnv, UNKNOWN).env;
break;
case RETURN:
{
Node retExp = n.getFirstChild();
if (retExp == null) {
inEnv = outEnv;
} else {
JSType declRetType = this.currentScope.getDeclaredTypeForOwnBody().getReturnType();
declRetType = firstNonNull(declRetType, UNKNOWN);
inEnv = analyzeExprBwd(retExp, outEnv, declRetType).env;
}
break;
}
case VAR:
{
if (NodeUtil.isTypedefDecl(n)) {
inEnv = outEnv;
break;
}
inEnv = outEnv;
for (Node nameNode = n.getFirstChild(); nameNode != null; nameNode = nameNode.getNext()) {
String varName = nameNode.getString();
Node rhs = nameNode.getFirstChild();
JSType declType = this.currentScope.getDeclaredTypeOf(varName);
inEnv = envPutType(inEnv, varName, UNKNOWN);
if (rhs == null || this.currentScope.isLocalFunDef(varName)) {
continue;
}
JSType inferredType = envGetType(outEnv, varName);
JSType requiredType;
if (declType == null) {
requiredType = inferredType;
} else {
// TODO(dimvar): look if the meet is needed
requiredType = JSType.meet(declType, inferredType);
requiredType = firstNonBottom(requiredType, UNKNOWN);
}
inEnv = analyzeExprBwd(rhs, inEnv, requiredType).env;
}
break;
}
case BLOCK:
case ROOT:
case BREAK:
case CATCH:
case CONTINUE:
case DEFAULT_CASE:
case DEBUGGER:
case EMPTY:
case SCRIPT:
case TRY:
case WITH:
inEnv = outEnv;
break;
case DO:
case FOR:
case FOR_IN:
case FOR_OF:
case IF:
case WHILE:
Node expr = (n.isForIn() || n.isForOf()) ? n.getFirstChild() : NodeUtil.getConditionExpression(n);
inEnv = analyzeExprBwd(expr, outEnv).env;
break;
case THROW:
case CASE:
case SWITCH:
inEnv = analyzeExprBwd(n.getFirstChild(), outEnv).env;
break;
default:
if (NodeUtil.isStatement(n)) {
throw new RuntimeException("Unhandled statement type: " + n.getToken());
} else {
inEnv = analyzeExprBwd(n, outEnv).env;
break;
}
}
println("\t\tinEnv: ", inEnv);
for (DiGraphEdge<Node, ControlFlowGraph.Branch> de : dn.getInEdges()) {
envs.put(de, inEnv);
}
}
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeExprBwd.
/**
* For now, we won't emit any warnings bwd.
*/
private EnvTypePair analyzeExprBwd(Node expr, TypeEnv outEnv, JSType requiredType) {
Preconditions.checkArgument(requiredType != null, "Required type null at: %s", expr);
checkArgument(!requiredType.isBottom());
switch(expr.getToken()) {
case // can be created by a FOR with empty condition
EMPTY:
return new EnvTypePair(outEnv, UNKNOWN);
case FUNCTION:
{
String fnName = symbolTable.getFunInternalName(expr);
return new EnvTypePair(outEnv, envGetType(outEnv, fnName));
}
case FALSE:
case NULL:
case NUMBER:
case STRING:
case TRUE:
return new EnvTypePair(outEnv, scalarValueToType(expr.getToken()));
case OBJECTLIT:
return analyzeObjLitBwd(expr, outEnv, requiredType);
case THIS:
{
// TODO(blickly): Infer a loose type for THIS if we're in a function.
if (!this.currentScope.hasThis()) {
return new EnvTypePair(outEnv, UNKNOWN);
}
JSType thisType = this.currentScope.getDeclaredTypeOf(THIS_ID);
return new EnvTypePair(outEnv, thisType);
}
case SUPER:
// us anything useful at the moment.
return new EnvTypePair(outEnv, UNKNOWN);
case NAME:
return analyzeNameBwd(expr, outEnv, requiredType);
case INC:
case DEC:
case BITNOT:
case // Unary operations on numbers
NEG:
return analyzeExprBwd(expr.getFirstChild(), outEnv, NUMBER);
case POS:
{
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = NUMBER;
return pair;
}
case TYPEOF:
{
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = STRING;
return pair;
}
case INSTANCEOF:
{
TypeEnv env = analyzeExprBwd(expr.getLastChild(), outEnv, commonTypes.topFunction()).env;
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), env);
pair.type = BOOLEAN;
return pair;
}
case BITOR:
case BITAND:
case BITXOR:
case DIV:
case EXPONENT:
case LSH:
case MOD:
case MUL:
case RSH:
case SUB:
case URSH:
return analyzeBinaryNumericOpBwd(expr, outEnv);
case ADD:
return analyzeAddBwd(expr, outEnv, requiredType);
case OR:
case AND:
return analyzeLogicalOpBwd(expr, outEnv);
case SHEQ:
case SHNE:
case EQ:
case NE:
return analyzeEqNeBwd(expr, outEnv);
case LT:
case GT:
case LE:
case GE:
return analyzeLtGtBwd(expr, outEnv);
case ASSIGN:
return analyzeAssignBwd(expr, outEnv, requiredType);
case ASSIGN_ADD:
return analyzeAssignAddBwd(expr, outEnv, requiredType);
case ASSIGN_BITOR:
case ASSIGN_BITXOR:
case ASSIGN_BITAND:
case ASSIGN_LSH:
case ASSIGN_RSH:
case ASSIGN_URSH:
case ASSIGN_SUB:
case ASSIGN_MUL:
case ASSIGN_DIV:
case ASSIGN_MOD:
case ASSIGN_EXPONENT:
return analyzeAssignNumericOpBwd(expr, outEnv);
case GETPROP:
{
checkState(!NodeUtil.isAssignmentOp(expr.getParent()) || !NodeUtil.isLValue(expr));
if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
return new EnvTypePair(outEnv, requiredType);
}
return analyzePropAccessBwd(expr.getFirstChild(), expr.getLastChild().getString(), outEnv, requiredType);
}
case HOOK:
return analyzeHookBwd(expr, outEnv, requiredType);
case CALL:
case NEW:
case TAGGED_TEMPLATELIT:
return analyzeInvocationBwd(expr, outEnv, requiredType);
case COMMA:
{
EnvTypePair pair = analyzeExprBwd(expr.getLastChild(), outEnv, requiredType);
pair.env = analyzeExprBwd(expr.getFirstChild(), pair.env).env;
return pair;
}
case NOT:
{
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = pair.type.negate();
return pair;
}
case GETELEM:
return analyzeGetElemBwd(expr, outEnv, requiredType);
case VOID:
{
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = UNDEFINED;
return pair;
}
case IN:
return analyzeInBwd(expr, outEnv);
case DELPROP:
{
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = BOOLEAN;
return pair;
}
case VAR:
{
// Can happen iff its parent is a for/in or for/of.
Node vdecl = expr.getFirstChild();
String name = vdecl.getString();
// For/in and for/of can never have rhs of its VAR
checkState(!vdecl.hasChildren());
return new EnvTypePair(envPutType(outEnv, name, UNKNOWN), UNKNOWN);
}
case REGEXP:
return new EnvTypePair(outEnv, commonTypes.getRegexpType());
case ARRAYLIT:
return analyzeArrayLitBwd(expr, outEnv);
case CAST:
{
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = (JSType) expr.getTypeI();
return pair;
}
case TEMPLATELIT:
return analyzeTemplateLitBwd(expr, outEnv);
case TEMPLATELIT_SUB:
return analyzeExprBwd(expr.getFirstChild(), outEnv, requiredType);
case STRING_KEY:
if (expr.hasChildren()) {
return analyzeExprBwd(expr.getFirstChild(), outEnv, requiredType);
} else {
return analyzeNameBwd(expr, outEnv, requiredType);
}
case MEMBER_FUNCTION_DEF:
return analyzeExprBwd(expr.getFirstChild(), outEnv, requiredType);
case COMPUTED_PROP:
TypeEnv env = analyzeExprBwd(expr.getSecondChild(), outEnv).env;
return analyzeExprBwd(expr.getFirstChild(), env);
case YIELD:
{
if (expr.hasChildren()) {
EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
pair.type = UNKNOWN;
return pair;
} else {
return new EnvTypePair(outEnv, UNKNOWN);
}
}
default:
throw new RuntimeException("BWD: Unhandled expression type: " + expr.getToken() + " with parent: " + expr.getParent());
}
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeHookFwd.
private EnvTypePair analyzeHookFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
Node cond = expr.getFirstChild();
Node thenBranch = cond.getNext();
Node elseBranch = thenBranch.getNext();
TypeEnv trueEnv = analyzeExprFwd(cond, inEnv, UNKNOWN, TRUTHY).env;
TypeEnv falseEnv = analyzeExprFwd(cond, inEnv, UNKNOWN, FALSY).env;
EnvTypePair thenPair = analyzeExprFwd(thenBranch, trueEnv, requiredType, specializedType);
EnvTypePair elsePair = analyzeExprFwd(elseBranch, falseEnv, requiredType, specializedType);
return EnvTypePair.join(thenPair, elsePair);
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeStrictComparisonFwd.
private EnvTypePair analyzeStrictComparisonFwd(Token comparisonOp, Node lhs, Node rhs, TypeEnv inEnv, JSType specializedType) {
if (specializedType.isTrueOrTruthy() || specializedType.isFalseOrFalsy()) {
if (lhs.isTypeOf()) {
return analyzeSpecializedTypeof(lhs, rhs, comparisonOp, inEnv, specializedType);
} else if (rhs.isTypeOf()) {
return analyzeSpecializedTypeof(rhs, lhs, comparisonOp, inEnv, specializedType);
} else if (isGoogTypeof(lhs)) {
return analyzeGoogTypeof(lhs, rhs, inEnv, specializedType);
} else if (isGoogTypeof(rhs)) {
return analyzeGoogTypeof(rhs, lhs, inEnv, specializedType);
}
}
EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv);
EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env);
JSType rhstype = rhsPair.type;
JSType lhstype = lhsPair.type;
if (!rhstype.isNullOrUndef()) {
if (JSType.haveCommonSubtype(lhstype, rhstype)) {
registerImplicitUses(lhs, lhstype, rhstype);
} else {
JSError error = JSError.make(lhs, INCOMPATIBLE_STRICT_COMPARISON, lhstype.toString(), rhstype.toString());
registerMismatchAndWarn(error, lhstype, rhstype);
}
}
// This env may contain types that have been tightened after nullable deref.
TypeEnv preciseEnv = rhsPair.env;
if ((comparisonOp == Token.SHEQ && specializedType.isTrueOrTruthy()) || (comparisonOp == Token.SHNE && specializedType.isFalseOrFalsy())) {
lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsPair.type.specialize(rhsPair.type));
rhsPair = analyzeExprFwd(rhs, lhsPair.env, UNKNOWN, rhsPair.type.specialize(lhsPair.type));
} else if ((comparisonOp == Token.SHEQ && specializedType.isFalseOrFalsy()) || (comparisonOp == Token.SHNE && specializedType.isTrueOrTruthy())) {
JSType lhsType = lhsPair.type;
JSType rhsType = rhsPair.type;
if (lhsType.isNullOrUndef()) {
rhsType = rhsType.removeType(lhsType);
} else if (rhsType.isNullOrUndef()) {
lhsType = lhsType.removeType(rhsType);
}
lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsType);
rhsPair = analyzeExprFwd(rhs, lhsPair.env, UNKNOWN, rhsType);
}
rhsPair.type = BOOLEAN;
return rhsPair;
}
Aggregations