All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eventb.core.ast.FreeIdentifier Maven / Gradle / Ivy

There is a newer version: 3.8.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2005, 2013 ETH Zurich and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     ETH Zurich - initial API and implementation
 *     Systerel - added accept for ISimpleVisitor
 *     Systerel - added support for predicate variables
 *     Systerel - generalised getPositions() into inspect()
 *     Systerel - externalized wd lemmas generation
 *     Systerel - added support for specialization
 *     Systerel - add given sets to free identifier cache
 *     Systerel - store factory used to build a formula
 *******************************************************************************/
package org.eventb.core.ast;

import static org.eventb.internal.core.ast.FormulaChecks.ensureHasType;
import static org.eventb.internal.core.ast.FormulaChecks.ensureValidIdentifierName;
import static org.eventb.internal.core.ast.GivenTypeHelper.getGivenTypeIdentifiers;
import static org.eventb.internal.core.ast.GivenTypeHelper.isGivenSet;
import static org.eventb.internal.core.ast.IdentListMerger.makeMerger;

import java.util.LinkedHashSet;
import java.util.Set;

import org.eventb.internal.core.ast.FindingAccumulator;
import org.eventb.internal.core.ast.ITypeCheckingRewriter;
import org.eventb.internal.core.ast.IdentListMerger;
import org.eventb.internal.core.ast.LegibilityResult;
import org.eventb.internal.core.typecheck.TypeCheckResult;
import org.eventb.internal.core.typecheck.TypeUnifier;

/**
 * This class represents either identifiers occurring free in an event-B
 * formula, or a bound identifier declaration.
 * 

* Identifiers which are bound by a quantifier are instance of the class * {@link org.eventb.core.ast.BoundIdentifier} instead. *

* * @author François Terrier * @since 1.0 * @noextend This class is not intended to be subclassed by clients. */ public class FreeIdentifier extends Identifier { // Suffix to be used for primed identifiers (after values of assigned variables) private static String primeSuffix = "'"; private final String name; /** * Must never be called directly: use the factory method instead. * * @see FormulaFactory#makeFreeIdentifier(String, SourceLocation) * @see FormulaFactory#makeFreeIdentifier(String, SourceLocation, Type) * * @since 3.0 */ protected FreeIdentifier(String name, SourceLocation location, Type type, FormulaFactory ff) { super(FREE_IDENT, ff, location, name.hashCode()); ensureValidIdentifierName(name, ff); this.name = name; ensureSameFactory(type); setPredicateVariableCache(); synthesizeType(type); ensureHasType(this, type); } /* * We must proceed in two steps for constructing the cache of free * identifiers. This is because this identifier is not typed initially and * therefore cannot be merged successfully. So we split the test in two * parts: we verify that this identifier name does not occur in the proposed * type BEFORE setting the type; once the type has been set, we compute the * free identifier cache. */ @Override protected void synthesizeType(Type proposedType) { this.freeIdents = new FreeIdentifier[] {this}; this.boundIdents = NO_BOUND_IDENT; if (proposedType == null) { return; } final FreeIdentifier[] givenTypeIdents; if (!isGivenSet(name, proposedType)) { // Check there is no occurrence of this identifier in given types givenTypeIdents = getGivenTypeIdentifiers(proposedType); for (final FreeIdentifier givenTypeIdent : givenTypeIdents) { if (name.equals(givenTypeIdent.getName())) { return; } } } else { givenTypeIdents = null; } setFinalType(proposedType, proposedType); if (givenTypeIdents != null) { final IdentListMerger merger = makeMerger(freeIdents, givenTypeIdents); this.freeIdents = merger.getFreeMergedArray(); assert !merger.containsError(); } } /** * Returns the name of this identifier. * * @return the name of this identifier */ public String getName() { return name; } /** * Returns the primed free identifier corresponding to this unprimed * identifier. *

* This identifier must not be primed. *

* * @return a copy of this identifier with a prime added * @since 3.0 */ public FreeIdentifier withPrime() { assert !isPrimed(); FreeIdentifier primedIdentifier = getFactory().makeFreeIdentifier( name + primeSuffix, getSourceLocation(), getType()); return primedIdentifier; } /** * Returns a declaration of a bound identifier, using this identifier as * model. * * @return a bound identifier declaration with the same properties as this * identifier * @since 3.0 */ public BoundIdentDecl asDecl() { BoundIdentDecl decl = getFactory().makeBoundIdentDecl( name, getSourceLocation(), getType()); return decl; } /** * Returns a primed declaration of a bound identifier, using this identifier * as model. *

* This is a short-hand for ident.withPrime().asDecl(), * implemented in a more efficient way. *

* * @return a bound identifier declaration with the same properties as this * identifier, except for the name which is primed * @since 3.0 */ public BoundIdentDecl asPrimedDecl() { assert !isPrimed(); BoundIdentDecl primedDecl = getFactory().makeBoundIdentDecl(name + primeSuffix, getSourceLocation(), getType()); return primedDecl; } /** * Returns the unprimed free identifier corresponding to this primed * identifier. *

* This identifier must be primed. *

* * @return a copy of this identifier with the prime removed * @since 3.0 */ public FreeIdentifier withoutPrime() { assert isPrimed(); FreeIdentifier unprimedIdentifier = getFactory().makeFreeIdentifier( name.substring(0, name.length() - primeSuffix.length()), getSourceLocation(), getType()); return unprimedIdentifier; } /** * Returns whether this identifier is primed. * * @return whether this identifier is primed */ public boolean isPrimed() { return name.endsWith(primeSuffix); } @Override protected String getSyntaxTree(String[] boundNames, String tabs) { final String typeName = getType()!=null?" [type: "+getType().toString()+"]":""; return tabs + this.getClass().getSimpleName() + " [name: " + name + "]" + typeName + "\n"; } @Override boolean equalsInternalExpr(Expression expr) { final FreeIdentifier other = (FreeIdentifier) expr; return name.equals(other.name); } /** * A formula containing free identifiers is well-formed, only if the free identifier * does not appear bound in the formula. * @since 2.0 */ @Override protected void isLegible(LegibilityResult result) { if (result.hasBoundIdentDecl(this.name)) { result.addProblem(new ASTProblem(this.getSourceLocation(), ProblemKind.FreeIdentifierHasBoundOccurences, ProblemSeverities.Error, this.name)); BoundIdentDecl temp = result.getExistingBoundIdentDecl(this.name); result.addProblem(new ASTProblem(temp.getSourceLocation(), ProblemKind.BoundIdentifierHasFreeOccurences, ProblemSeverities.Error, this.name)); } else if (! result.hasFreeIdent(this.name)) { result.addFreeIdent(this); } } @Override protected void typeCheck(TypeCheckResult result, BoundIdentDecl[] quantifiedIdentifiers) { setTemporaryType(result.getIdentType(this), result); result.analyzeExpression(this); } /** * @since 3.0 */ @Override protected void solveChildrenTypes(TypeUnifier unifier) { // No child } @Override protected void collectFreeIdentifiers(LinkedHashSet freeIdentSet) { freeIdentSet.add(this); } @Override protected void collectNamesAbove(Set names, String[] boundNames, int offset) { names.add(name); } @Override public boolean accept(IVisitor visitor) { return visitor.visitFREE_IDENT(this); } @Override public void accept(ISimpleVisitor visitor) { visitor.visitFreeIdentifier(this); } @Override protected Expression rewrite(ITypeCheckingRewriter rewriter) { return rewriter.rewrite(this); } @Override public boolean isATypeExpression() { Type myType = getType(); if (myType instanceof PowerSetType) { PowerSetType powerSetType = (PowerSetType) myType; Type baseType = powerSetType.getBaseType(); if (baseType instanceof GivenType) { GivenType givenType = (GivenType) baseType; return givenType.getName().equals(name); } } return false; } @Override public Type toType() { if (!isATypeExpression()) { return super.toType(); } return getFactory().makeGivenType(this); } @Override protected final void inspect(FindingAccumulator acc) { acc.inspect(this); if (acc.childrenSkipped()) { return; } } @Override public boolean isWDStrict() { return true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy