class ExprModel {

    public <T extends Expr> T register(T expr) {
        Preconditions.check(!mSealed, "Cannot add expressions to a model after it is sealed");
        Location location = null;
        if (mCurrentParserContext != null) {
            location = new Location(mCurrentParserContext);
            location.setParentLocation(mCurrentLocationInFile);
        }
        //noinspection unchecked
        T existing = (T) mExprMap.get(expr.getUniqueKey());
        if (existing != null) {
            Preconditions.check(expr.getParents().isEmpty(),
                    "If an expression already exists, it should've never been added to a parent,"
                            + "if thats the case, somewhere we are creating an expression w/o"
                            + "calling expression model");
            // tell the expr that it is being swapped so that if it was added to some other expr
            // as a parent, those can swap their references
            expr.onSwappedWith(existing);
            if (location != null) {
                existing.addLocation(location);
            }
            return existing;
        }
        mExprMap.put(expr.getUniqueKey(), expr);
        expr.setModel(this);
        if (location != null) {
            expr.addLocation(location);
        }
        return expr;
    }

}