Search in sources :

Example 1 with LocationTypeVar

use of org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar in project abstools by abstools.

the class ConstraintSolver method solve.

/**
 * Tries to find an optimal mapping from variables to location types in order to satisfy all constraints
 * @return - The found mapping
 */
public Map<LocationTypeVar, LocationType> solve() {
    Map<LocationTypeVar, LocationType> resolved = new HashMap<>();
    resolved.put(BOTTOM, LocationType.BOTTOM);
    resolved.put(NEAR, LocationType.NEAR);
    resolved.put(FAR, LocationType.FAR);
    resolved.put(SOMEWHERE, LocationType.SOMEWHERE);
    boolean changed;
    do {
        List<Constraint> workingSet = constraints.asList();
        for (Constraint c : workingSet) resolve(resolved, c);
        constraints.clear();
        changed = applyUpdates();
    } while (changed);
    for (Map.Entry<LocationTypeVar, LocationTypeVar> e : rewritten.entrySet()) {
        if (resolved.containsKey(e.getValue())) {
            resolved.put(e.getKey(), resolved.get(e.getValue()));
        }
    }
    for (LocationTypeVar v : allVars) {
        if (!resolved.containsKey(v)) {
            // Fallback to `SOMEWHERE`
            resolved.put(v, LocationType.SOMEWHERE);
        }
    }
    return resolved;
}
Also used : LocationTypeVar(org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar)

Example 2 with LocationTypeVar

use of org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar in project abstools by abstools.

the class ConstraintSolver method resolveSub.

/**
 * Resolve one sub constrained
 * @param resolved - Already resolved vars and their type
 * @param sub - The constraint to resolve
 */
private void resolveSub(Map<LocationTypeVar, LocationType> resolved, Constraint.Sub sub) {
    LocationTypeVar expected = getRewritten(sub.expected);
    LocationTypeVar actual = getRewritten(sub.actual);
    ASTNode<?> node = sub.node;
    if (expected == actual) {
        return;
    }
    if (expected.isLocationType() && actual.isLocationType()) {
        if (!expected.asLocationType().isSubtypeOf(actual.asLocationType())) {
            errors.add(new LocationTypeInferException(new TypeError(node, ErrorMessage.LOCATION_TYPE_CANNOT_ASSIGN, expected.toString(), actual.toString())));
        }
        return;
    }
    if (actual == BOTTOM) {
        throw new IllegalArgumentException("Cannot resolve constraint " + expected + " <: BOTTOM");
    }
    if (actual == NEAR) {
        add(Constraint.eq(expected, NEAR, node));
        return;
    }
    if (actual == FAR) {
        add(Constraint.eq(expected, FAR, node));
        return;
    }
    if (actual == SOMEWHERE) {
        // Useless
        return;
    }
    if (expected == SOMEWHERE) {
        add(Constraint.eq(actual, SOMEWHERE, node));
        return;
    }
    if (expected == BOTTOM) {
        // Useless
        return;
    }
    List<Constraint> expectedCs = constraints.get(expected);
    List<Constraint> actualCs = constraints.get(actual);
    if (expectedCs.size() <= 1 && actualCs.size() <= 1) {
        add(Constraint.eq(expected, actual, node));
        return;
    }
    if (actualCs.stream().filter(c -> c.isSub() && ((Constraint.Sub) c).actual == actual).count() == 1) {
        add(Constraint.eq(expected, actual, node));
        return;
    }
    if (expected == NEAR && actualCs.stream().anyMatch(c -> c.isSub() && ((Constraint.Sub) c).expected == FAR)) {
        add(Constraint.eq(actual, SOMEWHERE, node));
        return;
    }
    // Search for reverse (actual <: expected)
    // Search in smaller list
    List<Constraint> toSearch = expectedCs.size() < actualCs.size() ? expectedCs : actualCs;
    if (toSearch.stream().anyMatch(c -> c.isSub() && ((Constraint.Sub) c).expected == actual && ((Constraint.Sub) c).actual == expected)) {
        add(Constraint.eq(expected, actual, node));
        return;
    }
    keep(sub);
}
Also used : LocationTypeVar(org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar) java.util(java.util) SemanticConditionList(org.abs_models.frontend.analyser.SemanticConditionList) TypeError(org.abs_models.frontend.analyser.TypeError) AdaptDirection(org.abs_models.frontend.typechecker.ext.AdaptDirection) ASTNode(org.abs_models.frontend.ast.ASTNode) ErrorMessage(org.abs_models.frontend.analyser.ErrorMessage) TypeError(org.abs_models.frontend.analyser.TypeError) LocationTypeVar(org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar)

Example 3 with LocationTypeVar

use of org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar in project abstools by abstools.

the class ConstraintSolver method applyUpdates.

/**
 * Apply all updates we have collected this iteration
 * @return - Whether any changes have occurred
 */
private boolean applyUpdates() {
    boolean changed = false;
    for (Update u : updates) {
        Constraint c = u.constraint;
        for (LocationTypeVar v : u.constraint.vars()) if (rewritten.containsKey(v))
            c = c.replace(v, rewritten.get(v));
        switch(u.kind) {
            case ADD:
                changed = true;
                constraints.add(c);
                break;
            case REMOVE:
                changed = true;
                constraints.remove(c);
                break;
            case KEEP:
                constraints.add(c);
        }
    }
    updates.clear();
    return changed;
}
Also used : LocationTypeVar(org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar)

Example 4 with LocationTypeVar

use of org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar in project abstools by abstools.

the class ConstraintSolver method resolveAdapt.

/**
 * Resolve one adapt constrained
 * @param resolved - Already resolved vars and their type
 * @param adapt - The constraint to resolve
 */
private void resolveAdapt(Map<LocationTypeVar, LocationType> resolved, Constraint.Adapt adapt) {
    LocationTypeVar expected = getRewritten(adapt.expected);
    LocationTypeVar actual = getRewritten(adapt.actual);
    AdaptDirection dir = adapt.dir;
    LocationTypeVar adaptTo = getRewritten(adapt.adaptTo);
    ASTNode<?> node = adapt.node;
    if (!resolved.containsKey(adaptTo)) {
        keep(adapt);
        return;
    }
    if (adaptTo == NEAR) {
        add(Constraint.eq(expected, actual, node));
        return;
    }
    if (adaptTo == SOMEWHERE) {
        add(Constraint.eq(expected, SOMEWHERE, node));
        return;
    }
    if (adaptTo == FAR) {
        LocationTypeVar res;
        if (actual == NEAR) {
            res = FAR;
        } else if (actual == SOMEWHERE) {
            res = SOMEWHERE;
        } else if (actual == BOTTOM) {
            errors.add(new LocationTypeInferException(new TypeError(node, ErrorMessage.LOCATION_TYPE_CALL_ON_BOTTOM, new String[0])));
            return;
        } else if (actual == FAR) {
            res = SOMEWHERE;
        } else {
            keep(adapt);
            return;
        }
        add(Constraint.eq(expected, res, node));
        return;
    }
    keep(adapt);
}
Also used : TypeError(org.abs_models.frontend.analyser.TypeError) AdaptDirection(org.abs_models.frontend.typechecker.ext.AdaptDirection) LocationTypeVar(org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar)

Example 5 with LocationTypeVar

use of org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar in project abstools by abstools.

the class ConstraintSolver method resolveEq.

/**
 * Resolve one eq constrained
 * @param resolved - Already resolved vars and their type
 * @param eq - The constraint to resolve
 */
private void resolveEq(Map<LocationTypeVar, LocationType> resolved, Constraint.Eq eq) {
    LocationTypeVar expected = getRewritten(eq.expected);
    LocationTypeVar actual = getRewritten(eq.actual);
    ASTNode<?> node = eq.node;
    if (expected == actual)
        return;
    if (expected.isLocationType() && actual.isLocationType()) {
        errors.add(new LocationTypeInferException(new TypeError(node, ErrorMessage.LOCATION_TYPE_CANNOT_ASSIGN, expected.toString(), actual.toString())));
        return;
    }
    if (expected.isLocationType()) {
        rewrite(actual, expected);
        resolved.put(actual, expected.asLocationType());
        return;
    }
    if (actual.isLocationType()) {
        rewrite(expected, actual);
        resolved.put(expected, actual.asLocationType());
        return;
    }
    rewrite(expected, actual);
}
Also used : TypeError(org.abs_models.frontend.analyser.TypeError) LocationTypeVar(org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar)

Aggregations

LocationTypeVar (org.abs_models.frontend.typechecker.locationtypes.LocationTypeVar)5 TypeError (org.abs_models.frontend.analyser.TypeError)3 AdaptDirection (org.abs_models.frontend.typechecker.ext.AdaptDirection)2 java.util (java.util)1 ErrorMessage (org.abs_models.frontend.analyser.ErrorMessage)1 SemanticConditionList (org.abs_models.frontend.analyser.SemanticConditionList)1 ASTNode (org.abs_models.frontend.ast.ASTNode)1