Search in sources :

Example 21 with Pos

use of edu.mit.csail.sdg.alloy4.Pos in project org.alloytools.alloy by AlloyTools.

the class A4SolutionReader method parseField.

/**
 * Parse field.
 */
private Field parseField(String id) throws IOException, Err {
    final XMLNode node = nmap.get(id);
    if (node == null)
        throw new IOException("Unknown FieldID " + id + " encountered.");
    if (!node.is("field"))
        throw new IOException("ID " + id + " is not a field.");
    String label = label(node);
    Pos isPrivate = yes(node, "private") ? Pos.UNKNOWN : null;
    Pos isMeta = yes(node, "meta") ? Pos.UNKNOWN : null;
    Expr type = null;
    for (XMLNode sub : node) if (sub.is("types")) {
        Expr t = parseType(sub);
        if (type == null)
            type = t;
        else
            type = type.plus(t);
    }
    int arity;
    if (type == null || (arity = type.type().arity()) < 2)
        throw new IOException("Field " + label + " is maltyped.");
    String parentID = node.getAttribute("parentID");
    Sig parent = id2sig.get(parentID);
    if (parent == null)
        throw new IOException("ID " + parentID + " is not a sig.");
    Field field = null;
    for (Field f : parent.getFields()) if (f.label.equals(label) && f.type().arity() == arity && choices.contains(f)) {
        field = f;
        choices.remove(f);
        break;
    }
    if (field == null)
        field = parent.addTrickyField(Pos.UNKNOWN, isPrivate, null, null, isMeta, new String[] { label }, UNIV.join(type))[0];
    TupleSet ts = parseTuples(node, arity);
    expr2ts.put(field, ts);
    return field;
}
Also used : PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) Sig(edu.mit.csail.sdg.ast.Sig) Field(edu.mit.csail.sdg.ast.Sig.Field) TupleSet(kodkod.instance.TupleSet) XMLNode(edu.mit.csail.sdg.alloy4.XMLNode) Expr(edu.mit.csail.sdg.ast.Expr) Pos(edu.mit.csail.sdg.alloy4.Pos) IOException(java.io.IOException)

Example 22 with Pos

use of edu.mit.csail.sdg.alloy4.Pos in project org.alloytools.alloy by AlloyTools.

the class ExprBadCall method span.

/**
 * {@inheritDoc}
 */
@Override
public Pos span() {
    Pos p = span;
    if (p == null) {
        p = pos.merge(closingBracket);
        for (Expr a : args) p = p.merge(a.span());
        span = p;
    }
    return p;
}
Also used : Pos(edu.mit.csail.sdg.alloy4.Pos)

Example 23 with Pos

use of edu.mit.csail.sdg.alloy4.Pos in project org.alloytools.alloy by AlloyTools.

the class ExprBinary method resolve.

// ============================================================================================================//
/**
 * {@inheritDoc}
 */
@Override
public Expr resolve(Type p, Collection<ErrorWarning> warns) {
    if (errors.size() > 0)
        return this;
    ErrorWarning w = null;
    Type a = left.type, b = right.type;
    switch(op) {
        case MUL:
        case DIV:
        case REM:
        case LT:
        case LTE:
        case GT:
        case GTE:
        case SHL:
        case SHR:
        case SHA:
        case NOT_LTE:
        case NOT_GTE:
        case NOT_LT:
        case NOT_GT:
            {
                a = (b = Type.smallIntType());
                break;
            }
        case AND:
        case OR:
        case IFF:
        case IMPLIES:
            {
                a = (b = Type.FORMULA);
                break;
            }
        case EQUALS:
        case NOT_EQUALS:
            {
                p = a.intersect(b);
                if (p.hasTuple()) {
                    a = p;
                    b = p;
                } else {
                    a = a.pickCommonArity(b);
                    b = b.pickCommonArity(a);
                }
                // } else
                if (warns == null) {
                    break;
                } else if (left.type.hasTuple() && right.type.hasTuple() && !(left.type.intersects(right.type))) {
                    w = warn("== is redundant, because the left and right expressions are always disjoint.");
                } else if (left.isSame(right)) {
                    w = warn("== is redundant, because the left and right expressions always have the same value.");
                }
                break;
            }
        case IN:
        case NOT_IN:
            {
                a = a.pickCommonArity(b);
                b = b.intersect(a);
                if (warns == null)
                    break;
                if (left.type.hasNoTuple() && right.type.hasNoTuple())
                    w = warn("Subset operator is redundant, because both subexpressions are always empty.");
                else if (left.type.hasNoTuple())
                    w = warn("Subset operator is redundant, because the left subexpression is always empty.");
                else if (right.type.hasNoTuple())
                    w = warn("Subset operator is redundant, because the right subexpression is always empty.");
                else if (b.hasNoTuple())
                    w = warn("Subset operator is redundant, because the left and right subexpressions are always disjoint.");
                else if (left.isSame(right))
                    w = warn("Subset operator is redundant, because the left and right expressions always have the same value.");
                break;
            }
        case INTERSECT:
            {
                a = a.intersect(p);
                b = b.intersect(p);
                if (warns != null && type.hasNoTuple())
                    w = warn("& is irrelevant because the two subexpressions are always disjoint.");
                break;
            }
        case IPLUS:
        case IMINUS:
            {
                a = Type.smallIntType();
                b = Type.smallIntType();
                break;
            }
        case PLUSPLUS:
        case PLUS:
            {
                a = a.intersect(p);
                b = b.intersect(p);
                // b=Type.makeInt(b); }
                if (warns == null)
                    break;
                if (a == EMPTY && b == EMPTY)
                    w = warn(this + " is irrelevant since both subexpressions are redundant.", p);
                else if (a == EMPTY)
                    w = warn(this + " is irrelevant since the left subexpression is redundant.", p);
                else if (b == EMPTY || (op == Op.PLUSPLUS && !right.type.canOverride(left.type)))
                    w = warn(this + " is irrelevant since the right subexpression is redundant.", p);
                break;
            }
        case MINUS:
            {
                a = p;
                b = p.intersect(b);
                // } else
                if (warns != null && (type.hasNoTuple() || b.hasNoTuple())) {
                    w = warn("- is irrelevant since the right expression is redundant.", p);
                }
                break;
            }
        case JOIN:
            {
                if (warns != null && type.hasNoTuple())
                    w = warn("The join operation here always yields an empty set.");
                a = (b = EMPTY);
                for (ProductType aa : left.type) for (ProductType bb : right.type) if (p.hasArity(aa.arity() + bb.arity() - 2)) {
                    PrimSig j = aa.get(aa.arity() - 1).intersect(bb.get(0));
                    if (j != Sig.NONE)
                        for (ProductType cc : p.intersect(aa.join(bb))) if (!cc.isEmpty()) {
                            List<PrimSig> v = new ArrayList<PrimSig>(cc.arity() + 1);
                            for (int i = 0; i < cc.arity(); i++) v.add(cc.get(i));
                            v.add(aa.arity() - 1, j);
                            a = a.merge(Type.make(v, 0, aa.arity()));
                            b = b.merge(Type.make(v, aa.arity() - 1, v.size()));
                        }
                }
                if (a == EMPTY || b == EMPTY) {
                    // Continue the best we can; we
                    // should have issued a
                    // relevance warning elsewhere
                    // already.
                    a = (b = EMPTY);
                    for (ProductType aa : left.type) for (ProductType bb : right.type) if (p.hasArity(aa.arity() + bb.arity() - 2) && aa.get(aa.arity() - 1).intersects(bb.get(0))) {
                        a = a.merge(aa);
                        b = b.merge(bb);
                    }
                }
                if (a == EMPTY || b == EMPTY) {
                    // Continue the best we can; we
                    // should have issued a
                    // relevance warning elsewhere
                    // already.
                    a = (b = EMPTY);
                    for (ProductType aa : left.type) for (ProductType bb : right.type) if (p.hasArity(aa.arity() + bb.arity() - 2)) {
                        a = a.merge(aa);
                        b = b.merge(bb);
                    }
                }
                break;
            }
        case DOMAIN:
            {
                // leftType such that r1<:r2 in parentType}
                if (warns != null && type.hasNoTuple())
                    w = warn("<: is irrelevant because the result is always empty.");
                Type leftType = EMPTY, rightType = EMPTY;
                for (ProductType aa : a) if (aa.arity() == 1)
                    for (ProductType bb : b) if (p.hasArity(bb.arity()))
                        for (ProductType cc : p.intersect(bb.columnRestrict(aa.get(0), 0))) if (!cc.isEmpty()) {
                            leftType = leftType.merge(cc, 0, 1);
                            rightType = rightType.merge(cc);
                        }
                if (leftType == EMPTY || rightType == EMPTY) {
                    // We try to
                    // proceed the
                    // best we can
                    leftType = a.extract(1);
                    rightType = b.pickCommonArity(p);
                }
                a = leftType;
                b = rightType;
                break;
            }
        case RANGE:
            {
                // leftType such that r1:>r2 in parentType}
                if (warns != null && type.hasNoTuple())
                    w = warn(":> is irrelevant because the result is always empty.");
                Type leftType = EMPTY, rightType = EMPTY;
                for (ProductType bb : b) if (bb.arity() == 1)
                    for (ProductType aa : a) if (p.hasArity(aa.arity()))
                        for (ProductType cc : p.intersect(aa.columnRestrict(bb.get(0), aa.arity() - 1))) if (!cc.isEmpty()) {
                            leftType = leftType.merge(cc);
                            rightType = rightType.merge(cc, cc.arity() - 1, cc.arity());
                        }
                if (leftType == EMPTY || rightType == EMPTY) {
                    // We try to
                    // proceed the
                    // best we can
                    leftType = a.pickCommonArity(p);
                    rightType = b.extract(1);
                }
                a = leftType;
                b = rightType;
                break;
            }
        default:
            {
                // leftType such that r1->r2 in parentType}
                if (warns == null) {
                // do nothing
                } else if (a.hasTuple()) {
                    if (b.hasNoTuple())
                        w = warn("The left expression of -> is irrelevant because the right expression is always empty.");
                } else {
                    if (b.hasTuple())
                        w = warn("The right expression of -> is irrelevant because the left expression is always empty.");
                }
                Type leftType = EMPTY, rightType = EMPTY;
                for (ProductType aa : a) if (!aa.isEmpty())
                    for (ProductType bb : b) if (!bb.isEmpty() && p.hasArity(aa.arity() + bb.arity()))
                        for (ProductType cc : p.intersect(aa.product(bb))) if (!cc.isEmpty()) {
                            leftType = leftType.merge(cc, 0, aa.arity());
                            rightType = rightType.merge(cc, aa.arity(), cc.arity());
                        }
                // relevance warning already.
                if (leftType == EMPTY || rightType == EMPTY) {
                    leftType = a;
                    rightType = b;
                }
                a = leftType;
                b = rightType;
            }
    }
    Expr left = this.left.resolve(a, warns);
    Expr right = this.right.resolve(b, warns);
    if (w != null)
        warns.add(w);
    return (left == this.left && right == this.right) ? this : op.make(pos, closingBracket, left, right);
}
Also used : ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) ProductType(edu.mit.csail.sdg.ast.Type.ProductType) ProductType(edu.mit.csail.sdg.ast.Type.ProductType) ErrorWarning(edu.mit.csail.sdg.alloy4.ErrorWarning) ArrayList(java.util.ArrayList) List(java.util.List) JoinableList(edu.mit.csail.sdg.alloy4.JoinableList) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 24 with Pos

use of edu.mit.csail.sdg.alloy4.Pos in project org.alloytools.alloy by AlloyTools.

the class ExprCall method getSubnodes.

/**
 * {@inheritDoc}
 */
@Override
public List<? extends Browsable> getSubnodes() {
    if (args.size() == 0) {
        Expr b = fun.getBody();
        return Util.asList(make(b.pos(), b.span(), b.getHTML(), b.getSubnodes()));
    }
    Pos p = pos;
    if (p == Pos.UNKNOWN)
        p = span();
    Browsable f = make(p, p, (fun.isPred ? "<b>pred</b> " : "<b>fun</b> ") + fun.label, fun.getSubnodes());
    Browsable a = make(span(), span(), "<b>" + args.size() + " argument" + (args.size() == 1 ? "</b>" : "s</b>"), args);
    return Util.asList(f, a);
}
Also used : Pos(edu.mit.csail.sdg.alloy4.Pos)

Example 25 with Pos

use of edu.mit.csail.sdg.alloy4.Pos in project org.alloytools.alloy by AlloyTools.

the class ExprCall method make.

// ============================================================================================================//
/**
 * Constructs an ExprCall node with the given predicate/function "fun" and the
 * list of arguments "args".
 */
public static Expr make(Pos pos, Pos closingBracket, Func fun, List<Expr> args, long extraPenalty) {
    if (extraPenalty < 0)
        extraPenalty = 0;
    if (args == null)
        args = ConstList.make();
    long weight = extraPenalty;
    boolean ambiguous = false;
    JoinableList<Err> errs = emptyListOfErrors;
    TempList<Expr> newargs = new TempList<Expr>(args.size());
    if (args.size() != fun.count()) {
        errs = errs.make(new ErrorSyntax(pos, "" + fun + " has " + fun.count() + " parameters but is called with " + args.size() + " arguments."));
    }
    for (int i = 0; i < args.size(); i++) {
        final int a = (i < fun.count()) ? fun.get(i).type.arity() : 0;
        final Expr x = args.get(i).typecheck_as_set();
        ambiguous = ambiguous || x.ambiguous;
        errs = errs.make(x.errors);
        weight = weight + x.weight;
        if (x.mult != 0)
            errs = errs.make(new ErrorSyntax(x.span(), "Multiplicity expression not allowed here."));
        if (a > 0 && x.errors.isEmpty() && !x.type.hasArity(a))
            errs = errs.make(new ErrorType(x.span(), "This should have arity " + a + " but instead its possible type(s) are " + x.type));
        newargs.add(x);
    }
    Type t = Type.FORMULA;
    if (!fun.isPred && errs.size() == 0) {
        final Type tt = fun.returnDecl.type;
        try {
            // This provides a limited form of polymorphic function,
            // by using actual arguments at each call site to derive a
            // tighter bound on the return value.
            DeduceType d = new DeduceType();
            for (int i = 0; i < args.size(); i++) {
                ExprVar param = fun.get(i);
                d.env.put(param, newargs.get(i).type.extract(param.type.arity()));
            }
            t = fun.returnDecl.accept(d);
            if (t == null || t.is_int() || t.is_bool || t.arity() != tt.arity())
                // Just in case an error occurred...
                t = tt;
        } catch (Throwable ex) {
            // Just in case an error occurred...
            t = tt;
        }
    }
    return new ExprCall(pos, closingBracket, ambiguous, t, fun, newargs.makeConst(), extraPenalty, weight, errs);
}
Also used : Err(edu.mit.csail.sdg.alloy4.Err) ErrorSyntax(edu.mit.csail.sdg.alloy4.ErrorSyntax) ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) TempList(edu.mit.csail.sdg.alloy4.ConstList.TempList) ErrorType(edu.mit.csail.sdg.alloy4.ErrorType)

Aggregations

Pos (edu.mit.csail.sdg.alloy4.Pos)28 ErrorSyntax (edu.mit.csail.sdg.alloy4.ErrorSyntax)24 ErrorType (edu.mit.csail.sdg.alloy4.ErrorType)16 ArrayList (java.util.ArrayList)12 Expr (edu.mit.csail.sdg.ast.Expr)10 Sig (edu.mit.csail.sdg.ast.Sig)10 PrimSig (edu.mit.csail.sdg.ast.Sig.PrimSig)10 Err (edu.mit.csail.sdg.alloy4.Err)9 SubsetSig (edu.mit.csail.sdg.ast.Sig.SubsetSig)8 TempList (edu.mit.csail.sdg.alloy4.ConstList.TempList)7 LinkedHashMap (java.util.LinkedHashMap)7 ErrorFatal (edu.mit.csail.sdg.alloy4.ErrorFatal)6 Command (edu.mit.csail.sdg.ast.Command)5 ExprVar (edu.mit.csail.sdg.ast.ExprVar)5 Func (edu.mit.csail.sdg.ast.Func)5 IOException (java.io.IOException)5 Symbol (java_cup.runtime.Symbol)5 Field (edu.mit.csail.sdg.ast.Sig.Field)4 ErrorWarning (edu.mit.csail.sdg.alloy4.ErrorWarning)3 HashMap (java.util.HashMap)3